xref: /openbmc/linux/drivers/most/configfs.c (revision 2af4aa3b)
1b2765275SChristian Gromm // SPDX-License-Identifier: GPL-2.0
2b2765275SChristian Gromm /*
3b2765275SChristian Gromm  * configfs.c - Implementation of configfs interface to the driver stack
4b2765275SChristian Gromm  *
5b2765275SChristian Gromm  * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
6b2765275SChristian Gromm  */
7b2765275SChristian Gromm 
8b2765275SChristian Gromm #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9b2765275SChristian Gromm #include <linux/module.h>
10b2765275SChristian Gromm #include <linux/slab.h>
11b2765275SChristian Gromm #include <linux/init.h>
12b2765275SChristian Gromm #include <linux/configfs.h>
13b2765275SChristian Gromm #include <linux/most.h>
14b2765275SChristian Gromm 
15b2765275SChristian Gromm #define MAX_STRING_SIZE 80
16b2765275SChristian Gromm 
17b2765275SChristian Gromm struct mdev_link {
18b2765275SChristian Gromm 	struct config_item item;
19b2765275SChristian Gromm 	struct list_head list;
20b2765275SChristian Gromm 	bool create_link;
21b2765275SChristian Gromm 	bool destroy_link;
22b2765275SChristian Gromm 	u16 num_buffers;
23b2765275SChristian Gromm 	u16 buffer_size;
24b2765275SChristian Gromm 	u16 subbuffer_size;
25b2765275SChristian Gromm 	u16 packets_per_xact;
26b2765275SChristian Gromm 	u16 dbr_size;
27b2765275SChristian Gromm 	char datatype[MAX_STRING_SIZE];
28b2765275SChristian Gromm 	char direction[MAX_STRING_SIZE];
29b2765275SChristian Gromm 	char name[MAX_STRING_SIZE];
30b2765275SChristian Gromm 	char device[MAX_STRING_SIZE];
31b2765275SChristian Gromm 	char channel[MAX_STRING_SIZE];
32b2765275SChristian Gromm 	char comp[MAX_STRING_SIZE];
33b2765275SChristian Gromm 	char comp_params[MAX_STRING_SIZE];
34b2765275SChristian Gromm };
35b2765275SChristian Gromm 
36b2765275SChristian Gromm static struct list_head mdev_link_list;
37b2765275SChristian Gromm 
set_cfg_buffer_size(struct mdev_link * link)38b2765275SChristian Gromm static int set_cfg_buffer_size(struct mdev_link *link)
39b2765275SChristian Gromm {
40b2765275SChristian Gromm 	return most_set_cfg_buffer_size(link->device, link->channel,
41b2765275SChristian Gromm 					link->buffer_size);
42b2765275SChristian Gromm }
43b2765275SChristian Gromm 
set_cfg_subbuffer_size(struct mdev_link * link)44b2765275SChristian Gromm static int set_cfg_subbuffer_size(struct mdev_link *link)
45b2765275SChristian Gromm {
46b2765275SChristian Gromm 	return most_set_cfg_subbuffer_size(link->device, link->channel,
47b2765275SChristian Gromm 					   link->subbuffer_size);
48b2765275SChristian Gromm }
49b2765275SChristian Gromm 
set_cfg_dbr_size(struct mdev_link * link)50b2765275SChristian Gromm static int set_cfg_dbr_size(struct mdev_link *link)
51b2765275SChristian Gromm {
52b2765275SChristian Gromm 	return most_set_cfg_dbr_size(link->device, link->channel,
53b2765275SChristian Gromm 				     link->dbr_size);
54b2765275SChristian Gromm }
55b2765275SChristian Gromm 
set_cfg_num_buffers(struct mdev_link * link)56b2765275SChristian Gromm static int set_cfg_num_buffers(struct mdev_link *link)
57b2765275SChristian Gromm {
58b2765275SChristian Gromm 	return most_set_cfg_num_buffers(link->device, link->channel,
59b2765275SChristian Gromm 					link->num_buffers);
60b2765275SChristian Gromm }
61b2765275SChristian Gromm 
set_cfg_packets_xact(struct mdev_link * link)62b2765275SChristian Gromm static int set_cfg_packets_xact(struct mdev_link *link)
63b2765275SChristian Gromm {
64b2765275SChristian Gromm 	return most_set_cfg_packets_xact(link->device, link->channel,
65b2765275SChristian Gromm 					 link->packets_per_xact);
66b2765275SChristian Gromm }
67b2765275SChristian Gromm 
set_cfg_direction(struct mdev_link * link)68b2765275SChristian Gromm static int set_cfg_direction(struct mdev_link *link)
69b2765275SChristian Gromm {
70b2765275SChristian Gromm 	return most_set_cfg_direction(link->device, link->channel,
71b2765275SChristian Gromm 				      link->direction);
72b2765275SChristian Gromm }
73b2765275SChristian Gromm 
set_cfg_datatype(struct mdev_link * link)74b2765275SChristian Gromm static int set_cfg_datatype(struct mdev_link *link)
75b2765275SChristian Gromm {
76b2765275SChristian Gromm 	return most_set_cfg_datatype(link->device, link->channel,
77b2765275SChristian Gromm 				     link->datatype);
78b2765275SChristian Gromm }
79b2765275SChristian Gromm 
80b2765275SChristian Gromm static int (*set_config_val[])(struct mdev_link *link) = {
81b2765275SChristian Gromm 	set_cfg_buffer_size,
82b2765275SChristian Gromm 	set_cfg_subbuffer_size,
83b2765275SChristian Gromm 	set_cfg_dbr_size,
84b2765275SChristian Gromm 	set_cfg_num_buffers,
85b2765275SChristian Gromm 	set_cfg_packets_xact,
86b2765275SChristian Gromm 	set_cfg_direction,
87b2765275SChristian Gromm 	set_cfg_datatype,
88b2765275SChristian Gromm };
89b2765275SChristian Gromm 
to_mdev_link(struct config_item * item)90b2765275SChristian Gromm static struct mdev_link *to_mdev_link(struct config_item *item)
91b2765275SChristian Gromm {
92b2765275SChristian Gromm 	return container_of(item, struct mdev_link, item);
93b2765275SChristian Gromm }
94b2765275SChristian Gromm 
set_config_and_add_link(struct mdev_link * mdev_link)95b2765275SChristian Gromm static int set_config_and_add_link(struct mdev_link *mdev_link)
96b2765275SChristian Gromm {
97b2765275SChristian Gromm 	int i;
98b2765275SChristian Gromm 	int ret;
99b2765275SChristian Gromm 
100b2765275SChristian Gromm 	for (i = 0; i < ARRAY_SIZE(set_config_val); i++) {
101b2765275SChristian Gromm 		ret = set_config_val[i](mdev_link);
102b2765275SChristian Gromm 		if (ret < 0 && ret != -ENODEV) {
103b2765275SChristian Gromm 			pr_err("Config failed\n");
104b2765275SChristian Gromm 			return ret;
105b2765275SChristian Gromm 		}
106b2765275SChristian Gromm 	}
107b2765275SChristian Gromm 
108b2765275SChristian Gromm 	return most_add_link(mdev_link->device, mdev_link->channel,
109b2765275SChristian Gromm 			     mdev_link->comp, mdev_link->name,
110b2765275SChristian Gromm 			     mdev_link->comp_params);
111b2765275SChristian Gromm }
112b2765275SChristian Gromm 
mdev_link_create_link_store(struct config_item * item,const char * page,size_t count)113b2765275SChristian Gromm static ssize_t mdev_link_create_link_store(struct config_item *item,
114b2765275SChristian Gromm 					   const char *page, size_t count)
115b2765275SChristian Gromm {
116b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
117b2765275SChristian Gromm 	bool tmp;
118b2765275SChristian Gromm 	int ret;
119b2765275SChristian Gromm 
120b2765275SChristian Gromm 	ret = kstrtobool(page, &tmp);
121b2765275SChristian Gromm 	if (ret)
122b2765275SChristian Gromm 		return ret;
123b2765275SChristian Gromm 	if (!tmp)
124b2765275SChristian Gromm 		return count;
125b2765275SChristian Gromm 	ret = set_config_and_add_link(mdev_link);
126b2765275SChristian Gromm 	if (ret && ret != -ENODEV)
127b2765275SChristian Gromm 		return ret;
128b2765275SChristian Gromm 	list_add_tail(&mdev_link->list, &mdev_link_list);
129b2765275SChristian Gromm 	mdev_link->create_link = tmp;
130b2765275SChristian Gromm 	mdev_link->destroy_link = false;
131b2765275SChristian Gromm 
132b2765275SChristian Gromm 	return count;
133b2765275SChristian Gromm }
134b2765275SChristian Gromm 
mdev_link_destroy_link_store(struct config_item * item,const char * page,size_t count)135b2765275SChristian Gromm static ssize_t mdev_link_destroy_link_store(struct config_item *item,
136b2765275SChristian Gromm 					    const char *page, size_t count)
137b2765275SChristian Gromm {
138b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
139b2765275SChristian Gromm 	bool tmp;
140b2765275SChristian Gromm 	int ret;
141b2765275SChristian Gromm 
142b2765275SChristian Gromm 	ret = kstrtobool(page, &tmp);
143b2765275SChristian Gromm 	if (ret)
144b2765275SChristian Gromm 		return ret;
145b2765275SChristian Gromm 	if (!tmp)
146b2765275SChristian Gromm 		return count;
147b2765275SChristian Gromm 
148b2765275SChristian Gromm 	ret = most_remove_link(mdev_link->device, mdev_link->channel,
149b2765275SChristian Gromm 			       mdev_link->comp);
150b2765275SChristian Gromm 	if (ret)
151b2765275SChristian Gromm 		return ret;
152b2765275SChristian Gromm 	if (!list_empty(&mdev_link_list))
153b2765275SChristian Gromm 		list_del(&mdev_link->list);
154b2765275SChristian Gromm 
155b2765275SChristian Gromm 	mdev_link->destroy_link = tmp;
156b2765275SChristian Gromm 
157b2765275SChristian Gromm 	return count;
158b2765275SChristian Gromm }
159b2765275SChristian Gromm 
mdev_link_direction_show(struct config_item * item,char * page)160b2765275SChristian Gromm static ssize_t mdev_link_direction_show(struct config_item *item, char *page)
161b2765275SChristian Gromm {
162b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->direction);
163b2765275SChristian Gromm }
164b2765275SChristian Gromm 
mdev_link_direction_store(struct config_item * item,const char * page,size_t count)165b2765275SChristian Gromm static ssize_t mdev_link_direction_store(struct config_item *item,
166b2765275SChristian Gromm 					 const char *page, size_t count)
167b2765275SChristian Gromm {
168b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
169b2765275SChristian Gromm 
170b2765275SChristian Gromm 	if (!sysfs_streq(page, "dir_rx") && !sysfs_streq(page, "rx") &&
171b2765275SChristian Gromm 	    !sysfs_streq(page, "dir_tx") && !sysfs_streq(page, "tx"))
172b2765275SChristian Gromm 		return -EINVAL;
173b2765275SChristian Gromm 	strcpy(mdev_link->direction, page);
174b2765275SChristian Gromm 	strim(mdev_link->direction);
175b2765275SChristian Gromm 	return count;
176b2765275SChristian Gromm }
177b2765275SChristian Gromm 
mdev_link_datatype_show(struct config_item * item,char * page)178b2765275SChristian Gromm static ssize_t mdev_link_datatype_show(struct config_item *item, char *page)
179b2765275SChristian Gromm {
180b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->datatype);
181b2765275SChristian Gromm }
182b2765275SChristian Gromm 
mdev_link_datatype_store(struct config_item * item,const char * page,size_t count)183b2765275SChristian Gromm static ssize_t mdev_link_datatype_store(struct config_item *item,
184b2765275SChristian Gromm 					const char *page, size_t count)
185b2765275SChristian Gromm {
186b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
187b2765275SChristian Gromm 
188b2765275SChristian Gromm 	if (!sysfs_streq(page, "control") && !sysfs_streq(page, "async") &&
189b2765275SChristian Gromm 	    !sysfs_streq(page, "sync") && !sysfs_streq(page, "isoc") &&
190b2765275SChristian Gromm 	    !sysfs_streq(page, "isoc_avp"))
191b2765275SChristian Gromm 		return -EINVAL;
192b2765275SChristian Gromm 	strcpy(mdev_link->datatype, page);
193b2765275SChristian Gromm 	strim(mdev_link->datatype);
194b2765275SChristian Gromm 	return count;
195b2765275SChristian Gromm }
196b2765275SChristian Gromm 
mdev_link_device_show(struct config_item * item,char * page)197b2765275SChristian Gromm static ssize_t mdev_link_device_show(struct config_item *item, char *page)
198b2765275SChristian Gromm {
199b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->device);
200b2765275SChristian Gromm }
201b2765275SChristian Gromm 
mdev_link_device_store(struct config_item * item,const char * page,size_t count)202b2765275SChristian Gromm static ssize_t mdev_link_device_store(struct config_item *item,
203b2765275SChristian Gromm 				      const char *page, size_t count)
204b2765275SChristian Gromm {
205b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
206b2765275SChristian Gromm 
207*2af4aa3bSAzeem Shaikh 	strscpy(mdev_link->device, page, sizeof(mdev_link->device));
208b2765275SChristian Gromm 	strim(mdev_link->device);
209b2765275SChristian Gromm 	return count;
210b2765275SChristian Gromm }
211b2765275SChristian Gromm 
mdev_link_channel_show(struct config_item * item,char * page)212b2765275SChristian Gromm static ssize_t mdev_link_channel_show(struct config_item *item, char *page)
213b2765275SChristian Gromm {
214b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->channel);
215b2765275SChristian Gromm }
216b2765275SChristian Gromm 
mdev_link_channel_store(struct config_item * item,const char * page,size_t count)217b2765275SChristian Gromm static ssize_t mdev_link_channel_store(struct config_item *item,
218b2765275SChristian Gromm 				       const char *page, size_t count)
219b2765275SChristian Gromm {
220b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
221b2765275SChristian Gromm 
222*2af4aa3bSAzeem Shaikh 	strscpy(mdev_link->channel, page, sizeof(mdev_link->channel));
223b2765275SChristian Gromm 	strim(mdev_link->channel);
224b2765275SChristian Gromm 	return count;
225b2765275SChristian Gromm }
226b2765275SChristian Gromm 
mdev_link_comp_show(struct config_item * item,char * page)227b2765275SChristian Gromm static ssize_t mdev_link_comp_show(struct config_item *item, char *page)
228b2765275SChristian Gromm {
229b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->comp);
230b2765275SChristian Gromm }
231b2765275SChristian Gromm 
mdev_link_comp_store(struct config_item * item,const char * page,size_t count)232b2765275SChristian Gromm static ssize_t mdev_link_comp_store(struct config_item *item,
233b2765275SChristian Gromm 				    const char *page, size_t count)
234b2765275SChristian Gromm {
235b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
236b2765275SChristian Gromm 
237*2af4aa3bSAzeem Shaikh 	strscpy(mdev_link->comp, page, sizeof(mdev_link->comp));
238b2765275SChristian Gromm 	strim(mdev_link->comp);
239b2765275SChristian Gromm 	return count;
240b2765275SChristian Gromm }
241b2765275SChristian Gromm 
mdev_link_comp_params_show(struct config_item * item,char * page)242b2765275SChristian Gromm static ssize_t mdev_link_comp_params_show(struct config_item *item, char *page)
243b2765275SChristian Gromm {
244b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%s\n",
245b2765275SChristian Gromm 			to_mdev_link(item)->comp_params);
246b2765275SChristian Gromm }
247b2765275SChristian Gromm 
mdev_link_comp_params_store(struct config_item * item,const char * page,size_t count)248b2765275SChristian Gromm static ssize_t mdev_link_comp_params_store(struct config_item *item,
249b2765275SChristian Gromm 					   const char *page, size_t count)
250b2765275SChristian Gromm {
251b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
252b2765275SChristian Gromm 
253*2af4aa3bSAzeem Shaikh 	strscpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params));
254b2765275SChristian Gromm 	strim(mdev_link->comp_params);
255b2765275SChristian Gromm 	return count;
256b2765275SChristian Gromm }
257b2765275SChristian Gromm 
mdev_link_num_buffers_show(struct config_item * item,char * page)258b2765275SChristian Gromm static ssize_t mdev_link_num_buffers_show(struct config_item *item, char *page)
259b2765275SChristian Gromm {
260b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%d\n",
261b2765275SChristian Gromm 			to_mdev_link(item)->num_buffers);
262b2765275SChristian Gromm }
263b2765275SChristian Gromm 
mdev_link_num_buffers_store(struct config_item * item,const char * page,size_t count)264b2765275SChristian Gromm static ssize_t mdev_link_num_buffers_store(struct config_item *item,
265b2765275SChristian Gromm 					   const char *page, size_t count)
266b2765275SChristian Gromm {
267b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
268b2765275SChristian Gromm 	int ret;
269b2765275SChristian Gromm 
270b2765275SChristian Gromm 	ret = kstrtou16(page, 0, &mdev_link->num_buffers);
271b2765275SChristian Gromm 	if (ret)
272b2765275SChristian Gromm 		return ret;
273b2765275SChristian Gromm 	return count;
274b2765275SChristian Gromm }
275b2765275SChristian Gromm 
mdev_link_buffer_size_show(struct config_item * item,char * page)276b2765275SChristian Gromm static ssize_t mdev_link_buffer_size_show(struct config_item *item, char *page)
277b2765275SChristian Gromm {
278b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%d\n",
279b2765275SChristian Gromm 			to_mdev_link(item)->buffer_size);
280b2765275SChristian Gromm }
281b2765275SChristian Gromm 
mdev_link_buffer_size_store(struct config_item * item,const char * page,size_t count)282b2765275SChristian Gromm static ssize_t mdev_link_buffer_size_store(struct config_item *item,
283b2765275SChristian Gromm 					   const char *page, size_t count)
284b2765275SChristian Gromm {
285b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
286b2765275SChristian Gromm 	int ret;
287b2765275SChristian Gromm 
288b2765275SChristian Gromm 	ret = kstrtou16(page, 0, &mdev_link->buffer_size);
289b2765275SChristian Gromm 	if (ret)
290b2765275SChristian Gromm 		return ret;
291b2765275SChristian Gromm 	return count;
292b2765275SChristian Gromm }
293b2765275SChristian Gromm 
mdev_link_subbuffer_size_show(struct config_item * item,char * page)294b2765275SChristian Gromm static ssize_t mdev_link_subbuffer_size_show(struct config_item *item,
295b2765275SChristian Gromm 					     char *page)
296b2765275SChristian Gromm {
297b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%d\n",
298b2765275SChristian Gromm 			to_mdev_link(item)->subbuffer_size);
299b2765275SChristian Gromm }
300b2765275SChristian Gromm 
mdev_link_subbuffer_size_store(struct config_item * item,const char * page,size_t count)301b2765275SChristian Gromm static ssize_t mdev_link_subbuffer_size_store(struct config_item *item,
302b2765275SChristian Gromm 					      const char *page, size_t count)
303b2765275SChristian Gromm {
304b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
305b2765275SChristian Gromm 	int ret;
306b2765275SChristian Gromm 
307b2765275SChristian Gromm 	ret = kstrtou16(page, 0, &mdev_link->subbuffer_size);
308b2765275SChristian Gromm 	if (ret)
309b2765275SChristian Gromm 		return ret;
310b2765275SChristian Gromm 	return count;
311b2765275SChristian Gromm }
312b2765275SChristian Gromm 
mdev_link_packets_per_xact_show(struct config_item * item,char * page)313b2765275SChristian Gromm static ssize_t mdev_link_packets_per_xact_show(struct config_item *item,
314b2765275SChristian Gromm 					       char *page)
315b2765275SChristian Gromm {
316b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%d\n",
317b2765275SChristian Gromm 			to_mdev_link(item)->packets_per_xact);
318b2765275SChristian Gromm }
319b2765275SChristian Gromm 
mdev_link_packets_per_xact_store(struct config_item * item,const char * page,size_t count)320b2765275SChristian Gromm static ssize_t mdev_link_packets_per_xact_store(struct config_item *item,
321b2765275SChristian Gromm 						const char *page, size_t count)
322b2765275SChristian Gromm {
323b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
324b2765275SChristian Gromm 	int ret;
325b2765275SChristian Gromm 
326b2765275SChristian Gromm 	ret = kstrtou16(page, 0, &mdev_link->packets_per_xact);
327b2765275SChristian Gromm 	if (ret)
328b2765275SChristian Gromm 		return ret;
329b2765275SChristian Gromm 	return count;
330b2765275SChristian Gromm }
331b2765275SChristian Gromm 
mdev_link_dbr_size_show(struct config_item * item,char * page)332b2765275SChristian Gromm static ssize_t mdev_link_dbr_size_show(struct config_item *item, char *page)
333b2765275SChristian Gromm {
334b2765275SChristian Gromm 	return snprintf(page, PAGE_SIZE, "%d\n", to_mdev_link(item)->dbr_size);
335b2765275SChristian Gromm }
336b2765275SChristian Gromm 
mdev_link_dbr_size_store(struct config_item * item,const char * page,size_t count)337b2765275SChristian Gromm static ssize_t mdev_link_dbr_size_store(struct config_item *item,
338b2765275SChristian Gromm 					const char *page, size_t count)
339b2765275SChristian Gromm {
340b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
341b2765275SChristian Gromm 	int ret;
342b2765275SChristian Gromm 
343b2765275SChristian Gromm 	ret = kstrtou16(page, 0, &mdev_link->dbr_size);
344b2765275SChristian Gromm 	if (ret)
345b2765275SChristian Gromm 		return ret;
346b2765275SChristian Gromm 	return count;
347b2765275SChristian Gromm }
348b2765275SChristian Gromm 
349b2765275SChristian Gromm CONFIGFS_ATTR_WO(mdev_link_, create_link);
350b2765275SChristian Gromm CONFIGFS_ATTR_WO(mdev_link_, destroy_link);
351b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, device);
352b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, channel);
353b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, comp);
354b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, comp_params);
355b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, num_buffers);
356b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, buffer_size);
357b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, subbuffer_size);
358b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, packets_per_xact);
359b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, datatype);
360b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, direction);
361b2765275SChristian Gromm CONFIGFS_ATTR(mdev_link_, dbr_size);
362b2765275SChristian Gromm 
363b2765275SChristian Gromm static struct configfs_attribute *mdev_link_attrs[] = {
364b2765275SChristian Gromm 	&mdev_link_attr_create_link,
365b2765275SChristian Gromm 	&mdev_link_attr_destroy_link,
366b2765275SChristian Gromm 	&mdev_link_attr_device,
367b2765275SChristian Gromm 	&mdev_link_attr_channel,
368b2765275SChristian Gromm 	&mdev_link_attr_comp,
369b2765275SChristian Gromm 	&mdev_link_attr_comp_params,
370b2765275SChristian Gromm 	&mdev_link_attr_num_buffers,
371b2765275SChristian Gromm 	&mdev_link_attr_buffer_size,
372b2765275SChristian Gromm 	&mdev_link_attr_subbuffer_size,
373b2765275SChristian Gromm 	&mdev_link_attr_packets_per_xact,
374b2765275SChristian Gromm 	&mdev_link_attr_datatype,
375b2765275SChristian Gromm 	&mdev_link_attr_direction,
376b2765275SChristian Gromm 	&mdev_link_attr_dbr_size,
377b2765275SChristian Gromm 	NULL,
378b2765275SChristian Gromm };
379b2765275SChristian Gromm 
mdev_link_release(struct config_item * item)380b2765275SChristian Gromm static void mdev_link_release(struct config_item *item)
381b2765275SChristian Gromm {
382b2765275SChristian Gromm 	struct mdev_link *mdev_link = to_mdev_link(item);
383b2765275SChristian Gromm 	int ret;
384b2765275SChristian Gromm 
385b2765275SChristian Gromm 	if (mdev_link->destroy_link)
386b2765275SChristian Gromm 		goto free_item;
387b2765275SChristian Gromm 
388b2765275SChristian Gromm 	ret = most_remove_link(mdev_link->device, mdev_link->channel,
389b2765275SChristian Gromm 			       mdev_link->comp);
390b2765275SChristian Gromm 	if (ret) {
391b2765275SChristian Gromm 		pr_err("Removing link failed.\n");
392b2765275SChristian Gromm 		goto free_item;
393b2765275SChristian Gromm 	}
394b2765275SChristian Gromm 
395b2765275SChristian Gromm 	if (!list_empty(&mdev_link_list))
396b2765275SChristian Gromm 		list_del(&mdev_link->list);
397b2765275SChristian Gromm 
398b2765275SChristian Gromm free_item:
399b2765275SChristian Gromm 	kfree(to_mdev_link(item));
400b2765275SChristian Gromm }
401b2765275SChristian Gromm 
402b2765275SChristian Gromm static struct configfs_item_operations mdev_link_item_ops = {
403b2765275SChristian Gromm 	.release		= mdev_link_release,
404b2765275SChristian Gromm };
405b2765275SChristian Gromm 
406b2765275SChristian Gromm static const struct config_item_type mdev_link_type = {
407b2765275SChristian Gromm 	.ct_item_ops	= &mdev_link_item_ops,
408b2765275SChristian Gromm 	.ct_attrs	= mdev_link_attrs,
409b2765275SChristian Gromm 	.ct_owner	= THIS_MODULE,
410b2765275SChristian Gromm };
411b2765275SChristian Gromm 
412b2765275SChristian Gromm struct most_common {
413b2765275SChristian Gromm 	struct config_group group;
414b2765275SChristian Gromm 	struct module *mod;
415b2765275SChristian Gromm 	struct configfs_subsystem subsys;
416b2765275SChristian Gromm };
417b2765275SChristian Gromm 
to_most_common(struct configfs_subsystem * subsys)418b2765275SChristian Gromm static struct most_common *to_most_common(struct configfs_subsystem *subsys)
419b2765275SChristian Gromm {
420b2765275SChristian Gromm 	return container_of(subsys, struct most_common, subsys);
421b2765275SChristian Gromm }
422b2765275SChristian Gromm 
most_common_make_item(struct config_group * group,const char * name)423b2765275SChristian Gromm static struct config_item *most_common_make_item(struct config_group *group,
424b2765275SChristian Gromm 						 const char *name)
425b2765275SChristian Gromm {
426b2765275SChristian Gromm 	struct mdev_link *mdev_link;
427b2765275SChristian Gromm 	struct most_common *mc = to_most_common(group->cg_subsys);
428b2765275SChristian Gromm 
429b2765275SChristian Gromm 	mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
430b2765275SChristian Gromm 	if (!mdev_link)
431b2765275SChristian Gromm 		return ERR_PTR(-ENOMEM);
432b2765275SChristian Gromm 
433b2765275SChristian Gromm 	if (!try_module_get(mc->mod)) {
434b2765275SChristian Gromm 		kfree(mdev_link);
435b2765275SChristian Gromm 		return ERR_PTR(-ENOLCK);
436b2765275SChristian Gromm 	}
437b2765275SChristian Gromm 	config_item_init_type_name(&mdev_link->item, name,
438b2765275SChristian Gromm 				   &mdev_link_type);
439b2765275SChristian Gromm 
440b2765275SChristian Gromm 	if (!strcmp(group->cg_item.ci_namebuf, "most_cdev"))
441b2765275SChristian Gromm 		strcpy(mdev_link->comp, "cdev");
442b2765275SChristian Gromm 	else if (!strcmp(group->cg_item.ci_namebuf, "most_net"))
443b2765275SChristian Gromm 		strcpy(mdev_link->comp, "net");
444b2765275SChristian Gromm 	else if (!strcmp(group->cg_item.ci_namebuf, "most_video"))
445b2765275SChristian Gromm 		strcpy(mdev_link->comp, "video");
446b2765275SChristian Gromm 	strcpy(mdev_link->name, name);
447b2765275SChristian Gromm 	return &mdev_link->item;
448b2765275SChristian Gromm }
449b2765275SChristian Gromm 
most_common_release(struct config_item * item)450b2765275SChristian Gromm static void most_common_release(struct config_item *item)
451b2765275SChristian Gromm {
452b2765275SChristian Gromm 	struct config_group *group = to_config_group(item);
453b2765275SChristian Gromm 
454b2765275SChristian Gromm 	kfree(to_most_common(group->cg_subsys));
455b2765275SChristian Gromm }
456b2765275SChristian Gromm 
457b2765275SChristian Gromm static struct configfs_item_operations most_common_item_ops = {
458b2765275SChristian Gromm 	.release	= most_common_release,
459b2765275SChristian Gromm };
460b2765275SChristian Gromm 
most_common_disconnect(struct config_group * group,struct config_item * item)461b2765275SChristian Gromm static void most_common_disconnect(struct config_group *group,
462b2765275SChristian Gromm 				   struct config_item *item)
463b2765275SChristian Gromm {
464b2765275SChristian Gromm 	struct most_common *mc = to_most_common(group->cg_subsys);
465b2765275SChristian Gromm 
466b2765275SChristian Gromm 	module_put(mc->mod);
467b2765275SChristian Gromm }
468b2765275SChristian Gromm 
469b2765275SChristian Gromm static struct configfs_group_operations most_common_group_ops = {
470b2765275SChristian Gromm 	.make_item	= most_common_make_item,
471b2765275SChristian Gromm 	.disconnect_notify = most_common_disconnect,
472b2765275SChristian Gromm };
473b2765275SChristian Gromm 
474b2765275SChristian Gromm static const struct config_item_type most_common_type = {
475b2765275SChristian Gromm 	.ct_item_ops	= &most_common_item_ops,
476b2765275SChristian Gromm 	.ct_group_ops	= &most_common_group_ops,
477b2765275SChristian Gromm 	.ct_owner	= THIS_MODULE,
478b2765275SChristian Gromm };
479b2765275SChristian Gromm 
480b2765275SChristian Gromm static struct most_common most_cdev = {
481b2765275SChristian Gromm 	.subsys = {
482b2765275SChristian Gromm 		.su_group = {
483b2765275SChristian Gromm 			.cg_item = {
484b2765275SChristian Gromm 				.ci_namebuf = "most_cdev",
485b2765275SChristian Gromm 				.ci_type = &most_common_type,
486b2765275SChristian Gromm 			},
487b2765275SChristian Gromm 		},
488b2765275SChristian Gromm 	},
489b2765275SChristian Gromm };
490b2765275SChristian Gromm 
491b2765275SChristian Gromm static struct most_common most_net = {
492b2765275SChristian Gromm 	.subsys = {
493b2765275SChristian Gromm 		.su_group = {
494b2765275SChristian Gromm 			.cg_item = {
495b2765275SChristian Gromm 				.ci_namebuf = "most_net",
496b2765275SChristian Gromm 				.ci_type = &most_common_type,
497b2765275SChristian Gromm 			},
498b2765275SChristian Gromm 		},
499b2765275SChristian Gromm 	},
500b2765275SChristian Gromm };
501b2765275SChristian Gromm 
502b2765275SChristian Gromm static struct most_common most_video = {
503b2765275SChristian Gromm 	.subsys = {
504b2765275SChristian Gromm 		.su_group = {
505b2765275SChristian Gromm 			.cg_item = {
506b2765275SChristian Gromm 				.ci_namebuf = "most_video",
507b2765275SChristian Gromm 				.ci_type = &most_common_type,
508b2765275SChristian Gromm 			},
509b2765275SChristian Gromm 		},
510b2765275SChristian Gromm 	},
511b2765275SChristian Gromm };
512b2765275SChristian Gromm 
513b2765275SChristian Gromm struct most_snd_grp {
514b2765275SChristian Gromm 	struct config_group group;
515b2765275SChristian Gromm 	bool create_card;
516b2765275SChristian Gromm 	struct list_head list;
517b2765275SChristian Gromm };
518b2765275SChristian Gromm 
to_most_snd_grp(struct config_item * item)519b2765275SChristian Gromm static struct most_snd_grp *to_most_snd_grp(struct config_item *item)
520b2765275SChristian Gromm {
521b2765275SChristian Gromm 	return container_of(to_config_group(item), struct most_snd_grp, group);
522b2765275SChristian Gromm }
523b2765275SChristian Gromm 
most_snd_grp_make_item(struct config_group * group,const char * name)524b2765275SChristian Gromm static struct config_item *most_snd_grp_make_item(struct config_group *group,
525b2765275SChristian Gromm 						  const char *name)
526b2765275SChristian Gromm {
527b2765275SChristian Gromm 	struct mdev_link *mdev_link;
528b2765275SChristian Gromm 
529b2765275SChristian Gromm 	mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
530b2765275SChristian Gromm 	if (!mdev_link)
531b2765275SChristian Gromm 		return ERR_PTR(-ENOMEM);
532b2765275SChristian Gromm 
533b2765275SChristian Gromm 	config_item_init_type_name(&mdev_link->item, name, &mdev_link_type);
534b2765275SChristian Gromm 	mdev_link->create_link = false;
535b2765275SChristian Gromm 	strcpy(mdev_link->name, name);
536b2765275SChristian Gromm 	strcpy(mdev_link->comp, "sound");
537b2765275SChristian Gromm 	return &mdev_link->item;
538b2765275SChristian Gromm }
539b2765275SChristian Gromm 
most_snd_grp_create_card_store(struct config_item * item,const char * page,size_t count)540b2765275SChristian Gromm static ssize_t most_snd_grp_create_card_store(struct config_item *item,
541b2765275SChristian Gromm 					      const char *page, size_t count)
542b2765275SChristian Gromm {
543b2765275SChristian Gromm 	struct most_snd_grp *snd_grp = to_most_snd_grp(item);
544b2765275SChristian Gromm 	int ret;
545b2765275SChristian Gromm 	bool tmp;
546b2765275SChristian Gromm 
547b2765275SChristian Gromm 	ret = kstrtobool(page, &tmp);
548b2765275SChristian Gromm 	if (ret)
549b2765275SChristian Gromm 		return ret;
550b2765275SChristian Gromm 	if (tmp) {
551b2765275SChristian Gromm 		ret = most_cfg_complete("sound");
552b2765275SChristian Gromm 		if (ret)
553b2765275SChristian Gromm 			return ret;
554b2765275SChristian Gromm 	}
555b2765275SChristian Gromm 	snd_grp->create_card = tmp;
556b2765275SChristian Gromm 	return count;
557b2765275SChristian Gromm }
558b2765275SChristian Gromm 
559b2765275SChristian Gromm CONFIGFS_ATTR_WO(most_snd_grp_, create_card);
560b2765275SChristian Gromm 
561b2765275SChristian Gromm static struct configfs_attribute *most_snd_grp_attrs[] = {
562b2765275SChristian Gromm 	&most_snd_grp_attr_create_card,
563b2765275SChristian Gromm 	NULL,
564b2765275SChristian Gromm };
565b2765275SChristian Gromm 
most_snd_grp_release(struct config_item * item)566b2765275SChristian Gromm static void most_snd_grp_release(struct config_item *item)
567b2765275SChristian Gromm {
568b2765275SChristian Gromm 	struct most_snd_grp *group = to_most_snd_grp(item);
569b2765275SChristian Gromm 
570b2765275SChristian Gromm 	list_del(&group->list);
571b2765275SChristian Gromm 	kfree(group);
572b2765275SChristian Gromm }
573b2765275SChristian Gromm 
574b2765275SChristian Gromm static struct configfs_item_operations most_snd_grp_item_ops = {
575b2765275SChristian Gromm 	.release	= most_snd_grp_release,
576b2765275SChristian Gromm };
577b2765275SChristian Gromm 
578b2765275SChristian Gromm static struct configfs_group_operations most_snd_grp_group_ops = {
579b2765275SChristian Gromm 	.make_item	= most_snd_grp_make_item,
580b2765275SChristian Gromm };
581b2765275SChristian Gromm 
582b2765275SChristian Gromm static const struct config_item_type most_snd_grp_type = {
583b2765275SChristian Gromm 	.ct_item_ops	= &most_snd_grp_item_ops,
584b2765275SChristian Gromm 	.ct_group_ops	= &most_snd_grp_group_ops,
585b2765275SChristian Gromm 	.ct_attrs	= most_snd_grp_attrs,
586b2765275SChristian Gromm 	.ct_owner	= THIS_MODULE,
587b2765275SChristian Gromm };
588b2765275SChristian Gromm 
589b2765275SChristian Gromm struct most_sound {
590b2765275SChristian Gromm 	struct configfs_subsystem subsys;
591b2765275SChristian Gromm 	struct list_head soundcard_list;
592b2765275SChristian Gromm 	struct module *mod;
593b2765275SChristian Gromm };
594b2765275SChristian Gromm 
most_sound_make_group(struct config_group * group,const char * name)595b2765275SChristian Gromm static struct config_group *most_sound_make_group(struct config_group *group,
596b2765275SChristian Gromm 						  const char *name)
597b2765275SChristian Gromm {
598b2765275SChristian Gromm 	struct most_snd_grp *most;
599b2765275SChristian Gromm 	struct most_sound *ms = container_of(group->cg_subsys,
600b2765275SChristian Gromm 					     struct most_sound, subsys);
601b2765275SChristian Gromm 
602b2765275SChristian Gromm 	list_for_each_entry(most, &ms->soundcard_list, list) {
603b2765275SChristian Gromm 		if (!most->create_card) {
604b2765275SChristian Gromm 			pr_info("adapter configuration still in progress.\n");
605b2765275SChristian Gromm 			return ERR_PTR(-EPROTO);
606b2765275SChristian Gromm 		}
607b2765275SChristian Gromm 	}
608b2765275SChristian Gromm 	if (!try_module_get(ms->mod))
609b2765275SChristian Gromm 		return ERR_PTR(-ENOLCK);
610b2765275SChristian Gromm 	most = kzalloc(sizeof(*most), GFP_KERNEL);
611b2765275SChristian Gromm 	if (!most) {
612b2765275SChristian Gromm 		module_put(ms->mod);
613b2765275SChristian Gromm 		return ERR_PTR(-ENOMEM);
614b2765275SChristian Gromm 	}
615b2765275SChristian Gromm 	config_group_init_type_name(&most->group, name, &most_snd_grp_type);
616b2765275SChristian Gromm 	list_add_tail(&most->list, &ms->soundcard_list);
617b2765275SChristian Gromm 	return &most->group;
618b2765275SChristian Gromm }
619b2765275SChristian Gromm 
most_sound_disconnect(struct config_group * group,struct config_item * item)620b2765275SChristian Gromm static void most_sound_disconnect(struct config_group *group,
621b2765275SChristian Gromm 				  struct config_item *item)
622b2765275SChristian Gromm {
623b2765275SChristian Gromm 	struct most_sound *ms = container_of(group->cg_subsys,
624b2765275SChristian Gromm 					     struct most_sound, subsys);
625b2765275SChristian Gromm 	module_put(ms->mod);
626b2765275SChristian Gromm }
627b2765275SChristian Gromm 
628b2765275SChristian Gromm static struct configfs_group_operations most_sound_group_ops = {
629b2765275SChristian Gromm 	.make_group	= most_sound_make_group,
630b2765275SChristian Gromm 	.disconnect_notify = most_sound_disconnect,
631b2765275SChristian Gromm };
632b2765275SChristian Gromm 
633b2765275SChristian Gromm static const struct config_item_type most_sound_type = {
634b2765275SChristian Gromm 	.ct_group_ops	= &most_sound_group_ops,
635b2765275SChristian Gromm 	.ct_owner	= THIS_MODULE,
636b2765275SChristian Gromm };
637b2765275SChristian Gromm 
638b2765275SChristian Gromm static struct most_sound most_sound_subsys = {
639b2765275SChristian Gromm 	.subsys = {
640b2765275SChristian Gromm 		.su_group = {
641b2765275SChristian Gromm 			.cg_item = {
642b2765275SChristian Gromm 				.ci_namebuf = "most_sound",
643b2765275SChristian Gromm 				.ci_type = &most_sound_type,
644b2765275SChristian Gromm 			},
645b2765275SChristian Gromm 		},
646b2765275SChristian Gromm 	},
647b2765275SChristian Gromm };
648b2765275SChristian Gromm 
most_register_configfs_subsys(struct most_component * c)649b2765275SChristian Gromm int most_register_configfs_subsys(struct most_component *c)
650b2765275SChristian Gromm {
651b2765275SChristian Gromm 	int ret;
652b2765275SChristian Gromm 
653b2765275SChristian Gromm 	if (!strcmp(c->name, "cdev")) {
654b2765275SChristian Gromm 		most_cdev.mod = c->mod;
655b2765275SChristian Gromm 		ret = configfs_register_subsystem(&most_cdev.subsys);
656b2765275SChristian Gromm 	} else if (!strcmp(c->name, "net")) {
657b2765275SChristian Gromm 		most_net.mod = c->mod;
658b2765275SChristian Gromm 		ret = configfs_register_subsystem(&most_net.subsys);
659b2765275SChristian Gromm 	} else if (!strcmp(c->name, "video")) {
660b2765275SChristian Gromm 		most_video.mod = c->mod;
661b2765275SChristian Gromm 		ret = configfs_register_subsystem(&most_video.subsys);
662b2765275SChristian Gromm 	} else if (!strcmp(c->name, "sound")) {
663b2765275SChristian Gromm 		most_sound_subsys.mod = c->mod;
664b2765275SChristian Gromm 		ret = configfs_register_subsystem(&most_sound_subsys.subsys);
665b2765275SChristian Gromm 	} else {
666b2765275SChristian Gromm 		return -ENODEV;
667b2765275SChristian Gromm 	}
668b2765275SChristian Gromm 
669b2765275SChristian Gromm 	if (ret) {
670b2765275SChristian Gromm 		pr_err("Error %d while registering subsystem %s\n",
671b2765275SChristian Gromm 		       ret, c->name);
672b2765275SChristian Gromm 	}
673b2765275SChristian Gromm 	return ret;
674b2765275SChristian Gromm }
675b2765275SChristian Gromm EXPORT_SYMBOL_GPL(most_register_configfs_subsys);
676b2765275SChristian Gromm 
most_interface_register_notify(const char * mdev)677b2765275SChristian Gromm void most_interface_register_notify(const char *mdev)
678b2765275SChristian Gromm {
679b2765275SChristian Gromm 	bool register_snd_card = false;
680b2765275SChristian Gromm 	struct mdev_link *mdev_link;
681b2765275SChristian Gromm 
682b2765275SChristian Gromm 	list_for_each_entry(mdev_link, &mdev_link_list, list) {
683b2765275SChristian Gromm 		if (!strcmp(mdev_link->device, mdev)) {
684b2765275SChristian Gromm 			set_config_and_add_link(mdev_link);
685b2765275SChristian Gromm 			if (!strcmp(mdev_link->comp, "sound"))
686b2765275SChristian Gromm 				register_snd_card = true;
687b2765275SChristian Gromm 		}
688b2765275SChristian Gromm 	}
689b2765275SChristian Gromm 	if (register_snd_card)
690b2765275SChristian Gromm 		most_cfg_complete("sound");
691b2765275SChristian Gromm }
692b2765275SChristian Gromm 
most_deregister_configfs_subsys(struct most_component * c)693b2765275SChristian Gromm void most_deregister_configfs_subsys(struct most_component *c)
694b2765275SChristian Gromm {
695b2765275SChristian Gromm 	if (!strcmp(c->name, "cdev"))
696b2765275SChristian Gromm 		configfs_unregister_subsystem(&most_cdev.subsys);
697b2765275SChristian Gromm 	else if (!strcmp(c->name, "net"))
698b2765275SChristian Gromm 		configfs_unregister_subsystem(&most_net.subsys);
699b2765275SChristian Gromm 	else if (!strcmp(c->name, "video"))
700b2765275SChristian Gromm 		configfs_unregister_subsystem(&most_video.subsys);
701b2765275SChristian Gromm 	else if (!strcmp(c->name, "sound"))
702b2765275SChristian Gromm 		configfs_unregister_subsystem(&most_sound_subsys.subsys);
703b2765275SChristian Gromm }
704b2765275SChristian Gromm EXPORT_SYMBOL_GPL(most_deregister_configfs_subsys);
705b2765275SChristian Gromm 
configfs_init(void)706b2765275SChristian Gromm int __init configfs_init(void)
707b2765275SChristian Gromm {
708b2765275SChristian Gromm 	config_group_init(&most_cdev.subsys.su_group);
709b2765275SChristian Gromm 	mutex_init(&most_cdev.subsys.su_mutex);
710b2765275SChristian Gromm 
711b2765275SChristian Gromm 	config_group_init(&most_net.subsys.su_group);
712b2765275SChristian Gromm 	mutex_init(&most_net.subsys.su_mutex);
713b2765275SChristian Gromm 
714b2765275SChristian Gromm 	config_group_init(&most_video.subsys.su_group);
715b2765275SChristian Gromm 	mutex_init(&most_video.subsys.su_mutex);
716b2765275SChristian Gromm 
717b2765275SChristian Gromm 	config_group_init(&most_sound_subsys.subsys.su_group);
718b2765275SChristian Gromm 	mutex_init(&most_sound_subsys.subsys.su_mutex);
719b2765275SChristian Gromm 
720b2765275SChristian Gromm 	INIT_LIST_HEAD(&most_sound_subsys.soundcard_list);
721b2765275SChristian Gromm 	INIT_LIST_HEAD(&mdev_link_list);
722b2765275SChristian Gromm 
723b2765275SChristian Gromm 	return 0;
724b2765275SChristian Gromm }
725