18cfab3cfSBjorn Helgaas // SPDX-License-Identifier: GPL-2.0
29b41d19aSKrzysztof Kozlowski /*
3d7467991SKishon Vijay Abraham I * configfs to configure the PCI endpoint
4d7467991SKishon Vijay Abraham I *
5d7467991SKishon Vijay Abraham I * Copyright (C) 2017 Texas Instruments
6d7467991SKishon Vijay Abraham I * Author: Kishon Vijay Abraham I <kishon@ti.com>
7d7467991SKishon Vijay Abraham I */
8d7467991SKishon Vijay Abraham I
9d7467991SKishon Vijay Abraham I #include <linux/module.h>
10fc41df28SCyrille Pitchen #include <linux/idr.h>
11d7467991SKishon Vijay Abraham I #include <linux/slab.h>
12d7467991SKishon Vijay Abraham I
13d7467991SKishon Vijay Abraham I #include <linux/pci-epc.h>
14d7467991SKishon Vijay Abraham I #include <linux/pci-epf.h>
15d7467991SKishon Vijay Abraham I #include <linux/pci-ep-cfs.h>
16d7467991SKishon Vijay Abraham I
17fc41df28SCyrille Pitchen static DEFINE_IDR(functions_idr);
18fc41df28SCyrille Pitchen static DEFINE_MUTEX(functions_mutex);
19d7467991SKishon Vijay Abraham I static struct config_group *functions_group;
20d7467991SKishon Vijay Abraham I static struct config_group *controllers_group;
21d7467991SKishon Vijay Abraham I
22d7467991SKishon Vijay Abraham I struct pci_epf_group {
23d7467991SKishon Vijay Abraham I struct config_group group;
24e85a2d78SKishon Vijay Abraham I struct config_group primary_epc_group;
25e85a2d78SKishon Vijay Abraham I struct config_group secondary_epc_group;
2670b3740fSDamien Le Moal struct config_group *type_group;
27e85a2d78SKishon Vijay Abraham I struct delayed_work cfs_work;
28d7467991SKishon Vijay Abraham I struct pci_epf *epf;
29fc41df28SCyrille Pitchen int index;
30d7467991SKishon Vijay Abraham I };
31d7467991SKishon Vijay Abraham I
32d7467991SKishon Vijay Abraham I struct pci_epc_group {
33d7467991SKishon Vijay Abraham I struct config_group group;
34d7467991SKishon Vijay Abraham I struct pci_epc *epc;
35d7467991SKishon Vijay Abraham I bool start;
36d7467991SKishon Vijay Abraham I };
37d7467991SKishon Vijay Abraham I
to_pci_epf_group(struct config_item * item)38d7467991SKishon Vijay Abraham I static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
39d7467991SKishon Vijay Abraham I {
40d7467991SKishon Vijay Abraham I return container_of(to_config_group(item), struct pci_epf_group, group);
41d7467991SKishon Vijay Abraham I }
42d7467991SKishon Vijay Abraham I
to_pci_epc_group(struct config_item * item)43d7467991SKishon Vijay Abraham I static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
44d7467991SKishon Vijay Abraham I {
45d7467991SKishon Vijay Abraham I return container_of(to_config_group(item), struct pci_epc_group, group);
46d7467991SKishon Vijay Abraham I }
47d7467991SKishon Vijay Abraham I
pci_secondary_epc_epf_link(struct config_item * epf_item,struct config_item * epc_item)48e85a2d78SKishon Vijay Abraham I static int pci_secondary_epc_epf_link(struct config_item *epf_item,
49e85a2d78SKishon Vijay Abraham I struct config_item *epc_item)
50e85a2d78SKishon Vijay Abraham I {
51e85a2d78SKishon Vijay Abraham I int ret;
52e85a2d78SKishon Vijay Abraham I struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
53e85a2d78SKishon Vijay Abraham I struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
54e85a2d78SKishon Vijay Abraham I struct pci_epc *epc = epc_group->epc;
55e85a2d78SKishon Vijay Abraham I struct pci_epf *epf = epf_group->epf;
56e85a2d78SKishon Vijay Abraham I
57e85a2d78SKishon Vijay Abraham I ret = pci_epc_add_epf(epc, epf, SECONDARY_INTERFACE);
58e85a2d78SKishon Vijay Abraham I if (ret)
59e85a2d78SKishon Vijay Abraham I return ret;
60e85a2d78SKishon Vijay Abraham I
61e85a2d78SKishon Vijay Abraham I ret = pci_epf_bind(epf);
62e85a2d78SKishon Vijay Abraham I if (ret) {
63e85a2d78SKishon Vijay Abraham I pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE);
64e85a2d78SKishon Vijay Abraham I return ret;
65e85a2d78SKishon Vijay Abraham I }
66e85a2d78SKishon Vijay Abraham I
67e85a2d78SKishon Vijay Abraham I return 0;
68e85a2d78SKishon Vijay Abraham I }
69e85a2d78SKishon Vijay Abraham I
pci_secondary_epc_epf_unlink(struct config_item * epc_item,struct config_item * epf_item)70e85a2d78SKishon Vijay Abraham I static void pci_secondary_epc_epf_unlink(struct config_item *epc_item,
71e85a2d78SKishon Vijay Abraham I struct config_item *epf_item)
72e85a2d78SKishon Vijay Abraham I {
73e85a2d78SKishon Vijay Abraham I struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
74e85a2d78SKishon Vijay Abraham I struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
75e85a2d78SKishon Vijay Abraham I struct pci_epc *epc;
76e85a2d78SKishon Vijay Abraham I struct pci_epf *epf;
77e85a2d78SKishon Vijay Abraham I
78e85a2d78SKishon Vijay Abraham I WARN_ON_ONCE(epc_group->start);
79e85a2d78SKishon Vijay Abraham I
80e85a2d78SKishon Vijay Abraham I epc = epc_group->epc;
81e85a2d78SKishon Vijay Abraham I epf = epf_group->epf;
82e85a2d78SKishon Vijay Abraham I pci_epf_unbind(epf);
83e85a2d78SKishon Vijay Abraham I pci_epc_remove_epf(epc, epf, SECONDARY_INTERFACE);
84e85a2d78SKishon Vijay Abraham I }
85e85a2d78SKishon Vijay Abraham I
86e85a2d78SKishon Vijay Abraham I static struct configfs_item_operations pci_secondary_epc_item_ops = {
87e85a2d78SKishon Vijay Abraham I .allow_link = pci_secondary_epc_epf_link,
88e85a2d78SKishon Vijay Abraham I .drop_link = pci_secondary_epc_epf_unlink,
89e85a2d78SKishon Vijay Abraham I };
90e85a2d78SKishon Vijay Abraham I
91e85a2d78SKishon Vijay Abraham I static const struct config_item_type pci_secondary_epc_type = {
92e85a2d78SKishon Vijay Abraham I .ct_item_ops = &pci_secondary_epc_item_ops,
93e85a2d78SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
94e85a2d78SKishon Vijay Abraham I };
95e85a2d78SKishon Vijay Abraham I
96e85a2d78SKishon Vijay Abraham I static struct config_group
pci_ep_cfs_add_secondary_group(struct pci_epf_group * epf_group)97e85a2d78SKishon Vijay Abraham I *pci_ep_cfs_add_secondary_group(struct pci_epf_group *epf_group)
98e85a2d78SKishon Vijay Abraham I {
99e85a2d78SKishon Vijay Abraham I struct config_group *secondary_epc_group;
100e85a2d78SKishon Vijay Abraham I
101e85a2d78SKishon Vijay Abraham I secondary_epc_group = &epf_group->secondary_epc_group;
102e85a2d78SKishon Vijay Abraham I config_group_init_type_name(secondary_epc_group, "secondary",
103e85a2d78SKishon Vijay Abraham I &pci_secondary_epc_type);
104e85a2d78SKishon Vijay Abraham I configfs_register_group(&epf_group->group, secondary_epc_group);
105e85a2d78SKishon Vijay Abraham I
106e85a2d78SKishon Vijay Abraham I return secondary_epc_group;
107e85a2d78SKishon Vijay Abraham I }
108e85a2d78SKishon Vijay Abraham I
pci_primary_epc_epf_link(struct config_item * epf_item,struct config_item * epc_item)109e85a2d78SKishon Vijay Abraham I static int pci_primary_epc_epf_link(struct config_item *epf_item,
110e85a2d78SKishon Vijay Abraham I struct config_item *epc_item)
111e85a2d78SKishon Vijay Abraham I {
112e85a2d78SKishon Vijay Abraham I int ret;
113e85a2d78SKishon Vijay Abraham I struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
114e85a2d78SKishon Vijay Abraham I struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
115e85a2d78SKishon Vijay Abraham I struct pci_epc *epc = epc_group->epc;
116e85a2d78SKishon Vijay Abraham I struct pci_epf *epf = epf_group->epf;
117e85a2d78SKishon Vijay Abraham I
118e85a2d78SKishon Vijay Abraham I ret = pci_epc_add_epf(epc, epf, PRIMARY_INTERFACE);
119e85a2d78SKishon Vijay Abraham I if (ret)
120e85a2d78SKishon Vijay Abraham I return ret;
121e85a2d78SKishon Vijay Abraham I
122e85a2d78SKishon Vijay Abraham I ret = pci_epf_bind(epf);
123e85a2d78SKishon Vijay Abraham I if (ret) {
124e85a2d78SKishon Vijay Abraham I pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
125e85a2d78SKishon Vijay Abraham I return ret;
126e85a2d78SKishon Vijay Abraham I }
127e85a2d78SKishon Vijay Abraham I
128e85a2d78SKishon Vijay Abraham I return 0;
129e85a2d78SKishon Vijay Abraham I }
130e85a2d78SKishon Vijay Abraham I
pci_primary_epc_epf_unlink(struct config_item * epc_item,struct config_item * epf_item)131e85a2d78SKishon Vijay Abraham I static void pci_primary_epc_epf_unlink(struct config_item *epc_item,
132e85a2d78SKishon Vijay Abraham I struct config_item *epf_item)
133e85a2d78SKishon Vijay Abraham I {
134e85a2d78SKishon Vijay Abraham I struct pci_epf_group *epf_group = to_pci_epf_group(epf_item->ci_parent);
135e85a2d78SKishon Vijay Abraham I struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
136e85a2d78SKishon Vijay Abraham I struct pci_epc *epc;
137e85a2d78SKishon Vijay Abraham I struct pci_epf *epf;
138e85a2d78SKishon Vijay Abraham I
139e85a2d78SKishon Vijay Abraham I WARN_ON_ONCE(epc_group->start);
140e85a2d78SKishon Vijay Abraham I
141e85a2d78SKishon Vijay Abraham I epc = epc_group->epc;
142e85a2d78SKishon Vijay Abraham I epf = epf_group->epf;
143e85a2d78SKishon Vijay Abraham I pci_epf_unbind(epf);
144e85a2d78SKishon Vijay Abraham I pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
145e85a2d78SKishon Vijay Abraham I }
146e85a2d78SKishon Vijay Abraham I
147e85a2d78SKishon Vijay Abraham I static struct configfs_item_operations pci_primary_epc_item_ops = {
148e85a2d78SKishon Vijay Abraham I .allow_link = pci_primary_epc_epf_link,
149e85a2d78SKishon Vijay Abraham I .drop_link = pci_primary_epc_epf_unlink,
150e85a2d78SKishon Vijay Abraham I };
151e85a2d78SKishon Vijay Abraham I
152e85a2d78SKishon Vijay Abraham I static const struct config_item_type pci_primary_epc_type = {
153e85a2d78SKishon Vijay Abraham I .ct_item_ops = &pci_primary_epc_item_ops,
154e85a2d78SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
155e85a2d78SKishon Vijay Abraham I };
156e85a2d78SKishon Vijay Abraham I
157e85a2d78SKishon Vijay Abraham I static struct config_group
pci_ep_cfs_add_primary_group(struct pci_epf_group * epf_group)158e85a2d78SKishon Vijay Abraham I *pci_ep_cfs_add_primary_group(struct pci_epf_group *epf_group)
159e85a2d78SKishon Vijay Abraham I {
160e85a2d78SKishon Vijay Abraham I struct config_group *primary_epc_group = &epf_group->primary_epc_group;
161e85a2d78SKishon Vijay Abraham I
162e85a2d78SKishon Vijay Abraham I config_group_init_type_name(primary_epc_group, "primary",
163e85a2d78SKishon Vijay Abraham I &pci_primary_epc_type);
164e85a2d78SKishon Vijay Abraham I configfs_register_group(&epf_group->group, primary_epc_group);
165e85a2d78SKishon Vijay Abraham I
166e85a2d78SKishon Vijay Abraham I return primary_epc_group;
167e85a2d78SKishon Vijay Abraham I }
168e85a2d78SKishon Vijay Abraham I
pci_epc_start_store(struct config_item * item,const char * page,size_t len)169d7467991SKishon Vijay Abraham I static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
170d7467991SKishon Vijay Abraham I size_t len)
171d7467991SKishon Vijay Abraham I {
172d7467991SKishon Vijay Abraham I int ret;
173d7467991SKishon Vijay Abraham I bool start;
174d7467991SKishon Vijay Abraham I struct pci_epc *epc;
175d7467991SKishon Vijay Abraham I struct pci_epc_group *epc_group = to_pci_epc_group(item);
176d7467991SKishon Vijay Abraham I
177d7467991SKishon Vijay Abraham I epc = epc_group->epc;
178d7467991SKishon Vijay Abraham I
17936f354ecSKrzysztof Wilczyński if (kstrtobool(page, &start) < 0)
18036f354ecSKrzysztof Wilczyński return -EINVAL;
181d7467991SKishon Vijay Abraham I
182*a504c965SManivannan Sadhasivam if (start == epc_group->start)
183*a504c965SManivannan Sadhasivam return -EALREADY;
184*a504c965SManivannan Sadhasivam
185d7467991SKishon Vijay Abraham I if (!start) {
186d7467991SKishon Vijay Abraham I pci_epc_stop(epc);
187f58d5f53SKunihiko Hayashi epc_group->start = 0;
188d7467991SKishon Vijay Abraham I return len;
189d7467991SKishon Vijay Abraham I }
190d7467991SKishon Vijay Abraham I
191d7467991SKishon Vijay Abraham I ret = pci_epc_start(epc);
192d7467991SKishon Vijay Abraham I if (ret) {
193d7467991SKishon Vijay Abraham I dev_err(&epc->dev, "failed to start endpoint controller\n");
194d7467991SKishon Vijay Abraham I return -EINVAL;
195d7467991SKishon Vijay Abraham I }
196d7467991SKishon Vijay Abraham I
197d7467991SKishon Vijay Abraham I epc_group->start = start;
198d7467991SKishon Vijay Abraham I
199d7467991SKishon Vijay Abraham I return len;
200d7467991SKishon Vijay Abraham I }
201d7467991SKishon Vijay Abraham I
pci_epc_start_show(struct config_item * item,char * page)202d7467991SKishon Vijay Abraham I static ssize_t pci_epc_start_show(struct config_item *item, char *page)
203d7467991SKishon Vijay Abraham I {
204a2258831SKunihiko Hayashi return sysfs_emit(page, "%d\n", to_pci_epc_group(item)->start);
205d7467991SKishon Vijay Abraham I }
206d7467991SKishon Vijay Abraham I
207d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epc_, start);
208d7467991SKishon Vijay Abraham I
209d7467991SKishon Vijay Abraham I static struct configfs_attribute *pci_epc_attrs[] = {
210d7467991SKishon Vijay Abraham I &pci_epc_attr_start,
211d7467991SKishon Vijay Abraham I NULL,
212d7467991SKishon Vijay Abraham I };
213d7467991SKishon Vijay Abraham I
pci_epc_epf_link(struct config_item * epc_item,struct config_item * epf_item)214d7467991SKishon Vijay Abraham I static int pci_epc_epf_link(struct config_item *epc_item,
215d7467991SKishon Vijay Abraham I struct config_item *epf_item)
216d7467991SKishon Vijay Abraham I {
217d7467991SKishon Vijay Abraham I int ret;
218d7467991SKishon Vijay Abraham I struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
219d7467991SKishon Vijay Abraham I struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
2200c47cd7aSNiklas Cassel struct pci_epc *epc = epc_group->epc;
2210c47cd7aSNiklas Cassel struct pci_epf *epf = epf_group->epf;
222d7467991SKishon Vijay Abraham I
22363840ff5SKishon Vijay Abraham I ret = pci_epc_add_epf(epc, epf, PRIMARY_INTERFACE);
224d7467991SKishon Vijay Abraham I if (ret)
2252499ee84SKishon Vijay Abraham I return ret;
226d7467991SKishon Vijay Abraham I
227d7467991SKishon Vijay Abraham I ret = pci_epf_bind(epf);
2282499ee84SKishon Vijay Abraham I if (ret) {
22963840ff5SKishon Vijay Abraham I pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
2302499ee84SKishon Vijay Abraham I return ret;
2312499ee84SKishon Vijay Abraham I }
232d7467991SKishon Vijay Abraham I
233d7467991SKishon Vijay Abraham I return 0;
234d7467991SKishon Vijay Abraham I }
235d7467991SKishon Vijay Abraham I
pci_epc_epf_unlink(struct config_item * epc_item,struct config_item * epf_item)236d7467991SKishon Vijay Abraham I static void pci_epc_epf_unlink(struct config_item *epc_item,
237d7467991SKishon Vijay Abraham I struct config_item *epf_item)
238d7467991SKishon Vijay Abraham I {
239d7467991SKishon Vijay Abraham I struct pci_epc *epc;
240d7467991SKishon Vijay Abraham I struct pci_epf *epf;
241d7467991SKishon Vijay Abraham I struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
242d7467991SKishon Vijay Abraham I struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
243d7467991SKishon Vijay Abraham I
244d7467991SKishon Vijay Abraham I WARN_ON_ONCE(epc_group->start);
245d7467991SKishon Vijay Abraham I
246d7467991SKishon Vijay Abraham I epc = epc_group->epc;
247d7467991SKishon Vijay Abraham I epf = epf_group->epf;
248d7467991SKishon Vijay Abraham I pci_epf_unbind(epf);
24963840ff5SKishon Vijay Abraham I pci_epc_remove_epf(epc, epf, PRIMARY_INTERFACE);
250d7467991SKishon Vijay Abraham I }
251d7467991SKishon Vijay Abraham I
252d7467991SKishon Vijay Abraham I static struct configfs_item_operations pci_epc_item_ops = {
253d7467991SKishon Vijay Abraham I .allow_link = pci_epc_epf_link,
254d7467991SKishon Vijay Abraham I .drop_link = pci_epc_epf_unlink,
255d7467991SKishon Vijay Abraham I };
256d7467991SKishon Vijay Abraham I
2575c4e2476SBhumika Goyal static const struct config_item_type pci_epc_type = {
258d7467991SKishon Vijay Abraham I .ct_item_ops = &pci_epc_item_ops,
259d7467991SKishon Vijay Abraham I .ct_attrs = pci_epc_attrs,
260d7467991SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
261d7467991SKishon Vijay Abraham I };
262d7467991SKishon Vijay Abraham I
pci_ep_cfs_add_epc_group(const char * name)263d7467991SKishon Vijay Abraham I struct config_group *pci_ep_cfs_add_epc_group(const char *name)
264d7467991SKishon Vijay Abraham I {
265d7467991SKishon Vijay Abraham I int ret;
266d7467991SKishon Vijay Abraham I struct pci_epc *epc;
267d7467991SKishon Vijay Abraham I struct config_group *group;
268d7467991SKishon Vijay Abraham I struct pci_epc_group *epc_group;
269d7467991SKishon Vijay Abraham I
270d7467991SKishon Vijay Abraham I epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
271d7467991SKishon Vijay Abraham I if (!epc_group) {
272d7467991SKishon Vijay Abraham I ret = -ENOMEM;
273d7467991SKishon Vijay Abraham I goto err;
274d7467991SKishon Vijay Abraham I }
275d7467991SKishon Vijay Abraham I
276d7467991SKishon Vijay Abraham I group = &epc_group->group;
277d7467991SKishon Vijay Abraham I
278d7467991SKishon Vijay Abraham I config_group_init_type_name(group, name, &pci_epc_type);
279d7467991SKishon Vijay Abraham I ret = configfs_register_group(controllers_group, group);
280d7467991SKishon Vijay Abraham I if (ret) {
281d7467991SKishon Vijay Abraham I pr_err("failed to register configfs group for %s\n", name);
282d7467991SKishon Vijay Abraham I goto err_register_group;
283d7467991SKishon Vijay Abraham I }
284d7467991SKishon Vijay Abraham I
285d7467991SKishon Vijay Abraham I epc = pci_epc_get(name);
286d7467991SKishon Vijay Abraham I if (IS_ERR(epc)) {
287d7467991SKishon Vijay Abraham I ret = PTR_ERR(epc);
288d7467991SKishon Vijay Abraham I goto err_epc_get;
289d7467991SKishon Vijay Abraham I }
290d7467991SKishon Vijay Abraham I
291d7467991SKishon Vijay Abraham I epc_group->epc = epc;
292d7467991SKishon Vijay Abraham I
293d7467991SKishon Vijay Abraham I return group;
294d7467991SKishon Vijay Abraham I
295d7467991SKishon Vijay Abraham I err_epc_get:
296d7467991SKishon Vijay Abraham I configfs_unregister_group(group);
297d7467991SKishon Vijay Abraham I
298d7467991SKishon Vijay Abraham I err_register_group:
299d7467991SKishon Vijay Abraham I kfree(epc_group);
300d7467991SKishon Vijay Abraham I
301d7467991SKishon Vijay Abraham I err:
302d7467991SKishon Vijay Abraham I return ERR_PTR(ret);
303d7467991SKishon Vijay Abraham I }
304d7467991SKishon Vijay Abraham I EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
305d7467991SKishon Vijay Abraham I
pci_ep_cfs_remove_epc_group(struct config_group * group)306d7467991SKishon Vijay Abraham I void pci_ep_cfs_remove_epc_group(struct config_group *group)
307d7467991SKishon Vijay Abraham I {
308d7467991SKishon Vijay Abraham I struct pci_epc_group *epc_group;
309d7467991SKishon Vijay Abraham I
310d7467991SKishon Vijay Abraham I if (!group)
311d7467991SKishon Vijay Abraham I return;
312d7467991SKishon Vijay Abraham I
313d7467991SKishon Vijay Abraham I epc_group = container_of(group, struct pci_epc_group, group);
314d7467991SKishon Vijay Abraham I pci_epc_put(epc_group->epc);
315d7467991SKishon Vijay Abraham I configfs_unregister_group(&epc_group->group);
316d7467991SKishon Vijay Abraham I kfree(epc_group);
317d7467991SKishon Vijay Abraham I }
318d7467991SKishon Vijay Abraham I EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
319d7467991SKishon Vijay Abraham I
320d7467991SKishon Vijay Abraham I #define PCI_EPF_HEADER_R(_name) \
321d7467991SKishon Vijay Abraham I static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page) \
322d7467991SKishon Vijay Abraham I { \
323d7467991SKishon Vijay Abraham I struct pci_epf *epf = to_pci_epf_group(item)->epf; \
324d7467991SKishon Vijay Abraham I if (WARN_ON_ONCE(!epf->header)) \
325d7467991SKishon Vijay Abraham I return -EINVAL; \
326a2258831SKunihiko Hayashi return sysfs_emit(page, "0x%04x\n", epf->header->_name); \
327d7467991SKishon Vijay Abraham I }
328d7467991SKishon Vijay Abraham I
329d7467991SKishon Vijay Abraham I #define PCI_EPF_HEADER_W_u32(_name) \
330d7467991SKishon Vijay Abraham I static ssize_t pci_epf_##_name##_store(struct config_item *item, \
331d7467991SKishon Vijay Abraham I const char *page, size_t len) \
332d7467991SKishon Vijay Abraham I { \
333d7467991SKishon Vijay Abraham I u32 val; \
334d7467991SKishon Vijay Abraham I struct pci_epf *epf = to_pci_epf_group(item)->epf; \
335d7467991SKishon Vijay Abraham I if (WARN_ON_ONCE(!epf->header)) \
336d7467991SKishon Vijay Abraham I return -EINVAL; \
33736f354ecSKrzysztof Wilczyński if (kstrtou32(page, 0, &val) < 0) \
33836f354ecSKrzysztof Wilczyński return -EINVAL; \
339d7467991SKishon Vijay Abraham I epf->header->_name = val; \
340d7467991SKishon Vijay Abraham I return len; \
341d7467991SKishon Vijay Abraham I }
342d7467991SKishon Vijay Abraham I
343d7467991SKishon Vijay Abraham I #define PCI_EPF_HEADER_W_u16(_name) \
344d7467991SKishon Vijay Abraham I static ssize_t pci_epf_##_name##_store(struct config_item *item, \
345d7467991SKishon Vijay Abraham I const char *page, size_t len) \
346d7467991SKishon Vijay Abraham I { \
347d7467991SKishon Vijay Abraham I u16 val; \
348d7467991SKishon Vijay Abraham I struct pci_epf *epf = to_pci_epf_group(item)->epf; \
349d7467991SKishon Vijay Abraham I if (WARN_ON_ONCE(!epf->header)) \
350d7467991SKishon Vijay Abraham I return -EINVAL; \
35136f354ecSKrzysztof Wilczyński if (kstrtou16(page, 0, &val) < 0) \
35236f354ecSKrzysztof Wilczyński return -EINVAL; \
353d7467991SKishon Vijay Abraham I epf->header->_name = val; \
354d7467991SKishon Vijay Abraham I return len; \
355d7467991SKishon Vijay Abraham I }
356d7467991SKishon Vijay Abraham I
357d7467991SKishon Vijay Abraham I #define PCI_EPF_HEADER_W_u8(_name) \
358d7467991SKishon Vijay Abraham I static ssize_t pci_epf_##_name##_store(struct config_item *item, \
359d7467991SKishon Vijay Abraham I const char *page, size_t len) \
360d7467991SKishon Vijay Abraham I { \
361d7467991SKishon Vijay Abraham I u8 val; \
362d7467991SKishon Vijay Abraham I struct pci_epf *epf = to_pci_epf_group(item)->epf; \
363d7467991SKishon Vijay Abraham I if (WARN_ON_ONCE(!epf->header)) \
364d7467991SKishon Vijay Abraham I return -EINVAL; \
36536f354ecSKrzysztof Wilczyński if (kstrtou8(page, 0, &val) < 0) \
36636f354ecSKrzysztof Wilczyński return -EINVAL; \
367d7467991SKishon Vijay Abraham I epf->header->_name = val; \
368d7467991SKishon Vijay Abraham I return len; \
369d7467991SKishon Vijay Abraham I }
370d7467991SKishon Vijay Abraham I
pci_epf_msi_interrupts_store(struct config_item * item,const char * page,size_t len)371d7467991SKishon Vijay Abraham I static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
372d7467991SKishon Vijay Abraham I const char *page, size_t len)
373d7467991SKishon Vijay Abraham I {
374d7467991SKishon Vijay Abraham I u8 val;
375d7467991SKishon Vijay Abraham I
37636f354ecSKrzysztof Wilczyński if (kstrtou8(page, 0, &val) < 0)
37736f354ecSKrzysztof Wilczyński return -EINVAL;
378d7467991SKishon Vijay Abraham I
379d7467991SKishon Vijay Abraham I to_pci_epf_group(item)->epf->msi_interrupts = val;
380d7467991SKishon Vijay Abraham I
381d7467991SKishon Vijay Abraham I return len;
382d7467991SKishon Vijay Abraham I }
383d7467991SKishon Vijay Abraham I
pci_epf_msi_interrupts_show(struct config_item * item,char * page)384d7467991SKishon Vijay Abraham I static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
385d7467991SKishon Vijay Abraham I char *page)
386d7467991SKishon Vijay Abraham I {
387a2258831SKunihiko Hayashi return sysfs_emit(page, "%d\n",
388d7467991SKishon Vijay Abraham I to_pci_epf_group(item)->epf->msi_interrupts);
389d7467991SKishon Vijay Abraham I }
390d7467991SKishon Vijay Abraham I
pci_epf_msix_interrupts_store(struct config_item * item,const char * page,size_t len)3918963106eSGustavo Pimentel static ssize_t pci_epf_msix_interrupts_store(struct config_item *item,
3928963106eSGustavo Pimentel const char *page, size_t len)
3938963106eSGustavo Pimentel {
3948963106eSGustavo Pimentel u16 val;
3958963106eSGustavo Pimentel
39636f354ecSKrzysztof Wilczyński if (kstrtou16(page, 0, &val) < 0)
39736f354ecSKrzysztof Wilczyński return -EINVAL;
3988963106eSGustavo Pimentel
3998963106eSGustavo Pimentel to_pci_epf_group(item)->epf->msix_interrupts = val;
4008963106eSGustavo Pimentel
4018963106eSGustavo Pimentel return len;
4028963106eSGustavo Pimentel }
4038963106eSGustavo Pimentel
pci_epf_msix_interrupts_show(struct config_item * item,char * page)4048963106eSGustavo Pimentel static ssize_t pci_epf_msix_interrupts_show(struct config_item *item,
4058963106eSGustavo Pimentel char *page)
4068963106eSGustavo Pimentel {
407a2258831SKunihiko Hayashi return sysfs_emit(page, "%d\n",
4088963106eSGustavo Pimentel to_pci_epf_group(item)->epf->msix_interrupts);
4098963106eSGustavo Pimentel }
4108963106eSGustavo Pimentel
411d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(vendorid)
412d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u16(vendorid)
413d7467991SKishon Vijay Abraham I
414d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(deviceid)
415d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u16(deviceid)
416d7467991SKishon Vijay Abraham I
417d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(revid)
418d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u8(revid)
419d7467991SKishon Vijay Abraham I
420d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(progif_code)
421d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u8(progif_code)
422d7467991SKishon Vijay Abraham I
423d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(subclass_code)
424d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u8(subclass_code)
425d7467991SKishon Vijay Abraham I
426d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(baseclass_code)
427d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u8(baseclass_code)
428d7467991SKishon Vijay Abraham I
429d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(cache_line_size)
430d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u8(cache_line_size)
431d7467991SKishon Vijay Abraham I
432d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(subsys_vendor_id)
433d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u16(subsys_vendor_id)
434d7467991SKishon Vijay Abraham I
435d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(subsys_id)
436d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u16(subsys_id)
437d7467991SKishon Vijay Abraham I
438d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_R(interrupt_pin)
439d7467991SKishon Vijay Abraham I PCI_EPF_HEADER_W_u8(interrupt_pin)
440d7467991SKishon Vijay Abraham I
441d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, vendorid);
442d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, deviceid);
443d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, revid);
444d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, progif_code);
445d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, subclass_code);
446d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, baseclass_code);
447d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, cache_line_size);
448d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
449d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, subsys_id);
450d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, interrupt_pin);
451d7467991SKishon Vijay Abraham I CONFIGFS_ATTR(pci_epf_, msi_interrupts);
4528963106eSGustavo Pimentel CONFIGFS_ATTR(pci_epf_, msix_interrupts);
453d7467991SKishon Vijay Abraham I
454d7467991SKishon Vijay Abraham I static struct configfs_attribute *pci_epf_attrs[] = {
455d7467991SKishon Vijay Abraham I &pci_epf_attr_vendorid,
456d7467991SKishon Vijay Abraham I &pci_epf_attr_deviceid,
457d7467991SKishon Vijay Abraham I &pci_epf_attr_revid,
458d7467991SKishon Vijay Abraham I &pci_epf_attr_progif_code,
459d7467991SKishon Vijay Abraham I &pci_epf_attr_subclass_code,
460d7467991SKishon Vijay Abraham I &pci_epf_attr_baseclass_code,
461d7467991SKishon Vijay Abraham I &pci_epf_attr_cache_line_size,
462d7467991SKishon Vijay Abraham I &pci_epf_attr_subsys_vendor_id,
463d7467991SKishon Vijay Abraham I &pci_epf_attr_subsys_id,
464d7467991SKishon Vijay Abraham I &pci_epf_attr_interrupt_pin,
465d7467991SKishon Vijay Abraham I &pci_epf_attr_msi_interrupts,
4668963106eSGustavo Pimentel &pci_epf_attr_msix_interrupts,
467d7467991SKishon Vijay Abraham I NULL,
468d7467991SKishon Vijay Abraham I };
469d7467991SKishon Vijay Abraham I
pci_epf_vepf_link(struct config_item * epf_pf_item,struct config_item * epf_vf_item)470101600e7SKishon Vijay Abraham I static int pci_epf_vepf_link(struct config_item *epf_pf_item,
471101600e7SKishon Vijay Abraham I struct config_item *epf_vf_item)
472101600e7SKishon Vijay Abraham I {
473101600e7SKishon Vijay Abraham I struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
474101600e7SKishon Vijay Abraham I struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
475101600e7SKishon Vijay Abraham I struct pci_epf *epf_pf = epf_pf_group->epf;
476101600e7SKishon Vijay Abraham I struct pci_epf *epf_vf = epf_vf_group->epf;
477101600e7SKishon Vijay Abraham I
478101600e7SKishon Vijay Abraham I return pci_epf_add_vepf(epf_pf, epf_vf);
479101600e7SKishon Vijay Abraham I }
480101600e7SKishon Vijay Abraham I
pci_epf_vepf_unlink(struct config_item * epf_pf_item,struct config_item * epf_vf_item)481101600e7SKishon Vijay Abraham I static void pci_epf_vepf_unlink(struct config_item *epf_pf_item,
482101600e7SKishon Vijay Abraham I struct config_item *epf_vf_item)
483101600e7SKishon Vijay Abraham I {
484101600e7SKishon Vijay Abraham I struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
485101600e7SKishon Vijay Abraham I struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
486101600e7SKishon Vijay Abraham I struct pci_epf *epf_pf = epf_pf_group->epf;
487101600e7SKishon Vijay Abraham I struct pci_epf *epf_vf = epf_vf_group->epf;
488101600e7SKishon Vijay Abraham I
489101600e7SKishon Vijay Abraham I pci_epf_remove_vepf(epf_pf, epf_vf);
490101600e7SKishon Vijay Abraham I }
491101600e7SKishon Vijay Abraham I
pci_epf_release(struct config_item * item)492d7467991SKishon Vijay Abraham I static void pci_epf_release(struct config_item *item)
493d7467991SKishon Vijay Abraham I {
494d7467991SKishon Vijay Abraham I struct pci_epf_group *epf_group = to_pci_epf_group(item);
495d7467991SKishon Vijay Abraham I
496fc41df28SCyrille Pitchen mutex_lock(&functions_mutex);
497fc41df28SCyrille Pitchen idr_remove(&functions_idr, epf_group->index);
498fc41df28SCyrille Pitchen mutex_unlock(&functions_mutex);
499d7467991SKishon Vijay Abraham I pci_epf_destroy(epf_group->epf);
500d7467991SKishon Vijay Abraham I kfree(epf_group);
501d7467991SKishon Vijay Abraham I }
502d7467991SKishon Vijay Abraham I
503d7467991SKishon Vijay Abraham I static struct configfs_item_operations pci_epf_ops = {
504101600e7SKishon Vijay Abraham I .allow_link = pci_epf_vepf_link,
505101600e7SKishon Vijay Abraham I .drop_link = pci_epf_vepf_unlink,
506d7467991SKishon Vijay Abraham I .release = pci_epf_release,
507d7467991SKishon Vijay Abraham I };
508d7467991SKishon Vijay Abraham I
5095c4e2476SBhumika Goyal static const struct config_item_type pci_epf_type = {
510d7467991SKishon Vijay Abraham I .ct_item_ops = &pci_epf_ops,
511d7467991SKishon Vijay Abraham I .ct_attrs = pci_epf_attrs,
512d7467991SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
513d7467991SKishon Vijay Abraham I };
514d7467991SKishon Vijay Abraham I
515f6ec3397SDamien Le Moal /**
516f6ec3397SDamien Le Moal * pci_epf_type_add_cfs() - Help function drivers to expose function specific
517f6ec3397SDamien Le Moal * attributes in configfs
518f6ec3397SDamien Le Moal * @epf: the EPF device that has to be configured using configfs
519f6ec3397SDamien Le Moal * @group: the parent configfs group (corresponding to entries in
520f6ec3397SDamien Le Moal * pci_epf_device_id)
521f6ec3397SDamien Le Moal *
522f6ec3397SDamien Le Moal * Invoke to expose function specific attributes in configfs.
523f6ec3397SDamien Le Moal *
524f6ec3397SDamien Le Moal * Return: A pointer to a config_group structure or NULL if the function driver
525f6ec3397SDamien Le Moal * does not have anything to expose (attributes configured by user) or if
526f6ec3397SDamien Le Moal * the function driver does not implement the add_cfs() method.
527f6ec3397SDamien Le Moal *
528f6ec3397SDamien Le Moal * Returns an error pointer if this function is called for an unbound EPF device
529f6ec3397SDamien Le Moal * or if the EPF driver add_cfs() method fails.
530f6ec3397SDamien Le Moal */
pci_epf_type_add_cfs(struct pci_epf * epf,struct config_group * group)531f6ec3397SDamien Le Moal static struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf,
532f6ec3397SDamien Le Moal struct config_group *group)
533f6ec3397SDamien Le Moal {
534f6ec3397SDamien Le Moal struct config_group *epf_type_group;
535f6ec3397SDamien Le Moal
536f6ec3397SDamien Le Moal if (!epf->driver) {
537f6ec3397SDamien Le Moal dev_err(&epf->dev, "epf device not bound to driver\n");
538b6a6e033SDamien Le Moal return ERR_PTR(-ENODEV);
539f6ec3397SDamien Le Moal }
540f6ec3397SDamien Le Moal
541f6ec3397SDamien Le Moal if (!epf->driver->ops->add_cfs)
542f6ec3397SDamien Le Moal return NULL;
543f6ec3397SDamien Le Moal
544f6ec3397SDamien Le Moal mutex_lock(&epf->lock);
545f6ec3397SDamien Le Moal epf_type_group = epf->driver->ops->add_cfs(epf, group);
546f6ec3397SDamien Le Moal mutex_unlock(&epf->lock);
547f6ec3397SDamien Le Moal
548f6ec3397SDamien Le Moal return epf_type_group;
549f6ec3397SDamien Le Moal }
550f6ec3397SDamien Le Moal
pci_ep_cfs_add_type_group(struct pci_epf_group * epf_group)55170b3740fSDamien Le Moal static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group)
55270b3740fSDamien Le Moal {
55370b3740fSDamien Le Moal struct config_group *group;
55470b3740fSDamien Le Moal
55570b3740fSDamien Le Moal group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group);
55670b3740fSDamien Le Moal if (!group)
55770b3740fSDamien Le Moal return;
55870b3740fSDamien Le Moal
55970b3740fSDamien Le Moal if (IS_ERR(group)) {
56070b3740fSDamien Le Moal dev_err(&epf_group->epf->dev,
56170b3740fSDamien Le Moal "failed to create epf type specific attributes\n");
56270b3740fSDamien Le Moal return;
56370b3740fSDamien Le Moal }
56470b3740fSDamien Le Moal
56570b3740fSDamien Le Moal configfs_register_group(&epf_group->group, group);
56670b3740fSDamien Le Moal }
56770b3740fSDamien Le Moal
pci_epf_cfs_work(struct work_struct * work)568e85a2d78SKishon Vijay Abraham I static void pci_epf_cfs_work(struct work_struct *work)
569e85a2d78SKishon Vijay Abraham I {
570e85a2d78SKishon Vijay Abraham I struct pci_epf_group *epf_group;
571e85a2d78SKishon Vijay Abraham I struct config_group *group;
572e85a2d78SKishon Vijay Abraham I
573e85a2d78SKishon Vijay Abraham I epf_group = container_of(work, struct pci_epf_group, cfs_work.work);
574e85a2d78SKishon Vijay Abraham I group = pci_ep_cfs_add_primary_group(epf_group);
575e85a2d78SKishon Vijay Abraham I if (IS_ERR(group)) {
576e85a2d78SKishon Vijay Abraham I pr_err("failed to create 'primary' EPC interface\n");
577e85a2d78SKishon Vijay Abraham I return;
578e85a2d78SKishon Vijay Abraham I }
579e85a2d78SKishon Vijay Abraham I
580e85a2d78SKishon Vijay Abraham I group = pci_ep_cfs_add_secondary_group(epf_group);
581e85a2d78SKishon Vijay Abraham I if (IS_ERR(group)) {
582e85a2d78SKishon Vijay Abraham I pr_err("failed to create 'secondary' EPC interface\n");
583e85a2d78SKishon Vijay Abraham I return;
584e85a2d78SKishon Vijay Abraham I }
58570b3740fSDamien Le Moal
58670b3740fSDamien Le Moal pci_ep_cfs_add_type_group(epf_group);
587e85a2d78SKishon Vijay Abraham I }
588e85a2d78SKishon Vijay Abraham I
pci_epf_make(struct config_group * group,const char * name)589d7467991SKishon Vijay Abraham I static struct config_group *pci_epf_make(struct config_group *group,
590d7467991SKishon Vijay Abraham I const char *name)
591d7467991SKishon Vijay Abraham I {
592d7467991SKishon Vijay Abraham I struct pci_epf_group *epf_group;
593d7467991SKishon Vijay Abraham I struct pci_epf *epf;
594fc41df28SCyrille Pitchen char *epf_name;
595fc41df28SCyrille Pitchen int index, err;
596d7467991SKishon Vijay Abraham I
597d7467991SKishon Vijay Abraham I epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
598d7467991SKishon Vijay Abraham I if (!epf_group)
599d7467991SKishon Vijay Abraham I return ERR_PTR(-ENOMEM);
600d7467991SKishon Vijay Abraham I
601fc41df28SCyrille Pitchen mutex_lock(&functions_mutex);
602fc41df28SCyrille Pitchen index = idr_alloc(&functions_idr, epf_group, 0, 0, GFP_KERNEL);
603fc41df28SCyrille Pitchen mutex_unlock(&functions_mutex);
604fc41df28SCyrille Pitchen if (index < 0) {
605fc41df28SCyrille Pitchen err = index;
606fc41df28SCyrille Pitchen goto free_group;
607fc41df28SCyrille Pitchen }
608fc41df28SCyrille Pitchen
609fc41df28SCyrille Pitchen epf_group->index = index;
610fc41df28SCyrille Pitchen
611d7467991SKishon Vijay Abraham I config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
612d7467991SKishon Vijay Abraham I
613fc41df28SCyrille Pitchen epf_name = kasprintf(GFP_KERNEL, "%s.%d",
614fc41df28SCyrille Pitchen group->cg_item.ci_name, epf_group->index);
615fc41df28SCyrille Pitchen if (!epf_name) {
616fc41df28SCyrille Pitchen err = -ENOMEM;
617fc41df28SCyrille Pitchen goto remove_idr;
618fc41df28SCyrille Pitchen }
619fc41df28SCyrille Pitchen
620fc41df28SCyrille Pitchen epf = pci_epf_create(epf_name);
621d7467991SKishon Vijay Abraham I if (IS_ERR(epf)) {
622d7467991SKishon Vijay Abraham I pr_err("failed to create endpoint function device\n");
623fc41df28SCyrille Pitchen err = -EINVAL;
624fc41df28SCyrille Pitchen goto free_name;
625d7467991SKishon Vijay Abraham I }
626d7467991SKishon Vijay Abraham I
62738ad827eSKishon Vijay Abraham I epf->group = &epf_group->group;
628d7467991SKishon Vijay Abraham I epf_group->epf = epf;
629d7467991SKishon Vijay Abraham I
630fc41df28SCyrille Pitchen kfree(epf_name);
631fc41df28SCyrille Pitchen
632e85a2d78SKishon Vijay Abraham I INIT_DELAYED_WORK(&epf_group->cfs_work, pci_epf_cfs_work);
633e85a2d78SKishon Vijay Abraham I queue_delayed_work(system_wq, &epf_group->cfs_work,
634e85a2d78SKishon Vijay Abraham I msecs_to_jiffies(1));
635e85a2d78SKishon Vijay Abraham I
636d7467991SKishon Vijay Abraham I return &epf_group->group;
637fc41df28SCyrille Pitchen
638fc41df28SCyrille Pitchen free_name:
639fc41df28SCyrille Pitchen kfree(epf_name);
640fc41df28SCyrille Pitchen
641fc41df28SCyrille Pitchen remove_idr:
642fc41df28SCyrille Pitchen mutex_lock(&functions_mutex);
643fc41df28SCyrille Pitchen idr_remove(&functions_idr, epf_group->index);
644fc41df28SCyrille Pitchen mutex_unlock(&functions_mutex);
645fc41df28SCyrille Pitchen
646fc41df28SCyrille Pitchen free_group:
647fc41df28SCyrille Pitchen kfree(epf_group);
648fc41df28SCyrille Pitchen
649fc41df28SCyrille Pitchen return ERR_PTR(err);
650d7467991SKishon Vijay Abraham I }
651d7467991SKishon Vijay Abraham I
pci_epf_drop(struct config_group * group,struct config_item * item)652d7467991SKishon Vijay Abraham I static void pci_epf_drop(struct config_group *group, struct config_item *item)
653d7467991SKishon Vijay Abraham I {
654d7467991SKishon Vijay Abraham I config_item_put(item);
655d7467991SKishon Vijay Abraham I }
656d7467991SKishon Vijay Abraham I
657d7467991SKishon Vijay Abraham I static struct configfs_group_operations pci_epf_group_ops = {
658d7467991SKishon Vijay Abraham I .make_group = &pci_epf_make,
659d7467991SKishon Vijay Abraham I .drop_item = &pci_epf_drop,
660d7467991SKishon Vijay Abraham I };
661d7467991SKishon Vijay Abraham I
6625c4e2476SBhumika Goyal static const struct config_item_type pci_epf_group_type = {
663d7467991SKishon Vijay Abraham I .ct_group_ops = &pci_epf_group_ops,
664d7467991SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
665d7467991SKishon Vijay Abraham I };
666d7467991SKishon Vijay Abraham I
pci_ep_cfs_add_epf_group(const char * name)667d7467991SKishon Vijay Abraham I struct config_group *pci_ep_cfs_add_epf_group(const char *name)
668d7467991SKishon Vijay Abraham I {
669d7467991SKishon Vijay Abraham I struct config_group *group;
670d7467991SKishon Vijay Abraham I
671d7467991SKishon Vijay Abraham I group = configfs_register_default_group(functions_group, name,
672d7467991SKishon Vijay Abraham I &pci_epf_group_type);
673d7467991SKishon Vijay Abraham I if (IS_ERR(group))
674d7467991SKishon Vijay Abraham I pr_err("failed to register configfs group for %s function\n",
675d7467991SKishon Vijay Abraham I name);
676d7467991SKishon Vijay Abraham I
677d7467991SKishon Vijay Abraham I return group;
678d7467991SKishon Vijay Abraham I }
679d7467991SKishon Vijay Abraham I EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
680d7467991SKishon Vijay Abraham I
pci_ep_cfs_remove_epf_group(struct config_group * group)681d7467991SKishon Vijay Abraham I void pci_ep_cfs_remove_epf_group(struct config_group *group)
682d7467991SKishon Vijay Abraham I {
683d7467991SKishon Vijay Abraham I if (IS_ERR_OR_NULL(group))
684d7467991SKishon Vijay Abraham I return;
685d7467991SKishon Vijay Abraham I
686d7467991SKishon Vijay Abraham I configfs_unregister_default_group(group);
687d7467991SKishon Vijay Abraham I }
688d7467991SKishon Vijay Abraham I EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
689d7467991SKishon Vijay Abraham I
6905c4e2476SBhumika Goyal static const struct config_item_type pci_functions_type = {
691d7467991SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
692d7467991SKishon Vijay Abraham I };
693d7467991SKishon Vijay Abraham I
6945c4e2476SBhumika Goyal static const struct config_item_type pci_controllers_type = {
695d7467991SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
696d7467991SKishon Vijay Abraham I };
697d7467991SKishon Vijay Abraham I
6985c4e2476SBhumika Goyal static const struct config_item_type pci_ep_type = {
699d7467991SKishon Vijay Abraham I .ct_owner = THIS_MODULE,
700d7467991SKishon Vijay Abraham I };
701d7467991SKishon Vijay Abraham I
702d7467991SKishon Vijay Abraham I static struct configfs_subsystem pci_ep_cfs_subsys = {
703d7467991SKishon Vijay Abraham I .su_group = {
704d7467991SKishon Vijay Abraham I .cg_item = {
705d7467991SKishon Vijay Abraham I .ci_namebuf = "pci_ep",
706d7467991SKishon Vijay Abraham I .ci_type = &pci_ep_type,
707d7467991SKishon Vijay Abraham I },
708d7467991SKishon Vijay Abraham I },
709d7467991SKishon Vijay Abraham I .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
710d7467991SKishon Vijay Abraham I };
711d7467991SKishon Vijay Abraham I
pci_ep_cfs_init(void)712d7467991SKishon Vijay Abraham I static int __init pci_ep_cfs_init(void)
713d7467991SKishon Vijay Abraham I {
714d7467991SKishon Vijay Abraham I int ret;
715d7467991SKishon Vijay Abraham I struct config_group *root = &pci_ep_cfs_subsys.su_group;
716d7467991SKishon Vijay Abraham I
717d7467991SKishon Vijay Abraham I config_group_init(root);
718d7467991SKishon Vijay Abraham I
719d7467991SKishon Vijay Abraham I ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
720d7467991SKishon Vijay Abraham I if (ret) {
721d7467991SKishon Vijay Abraham I pr_err("Error %d while registering subsystem %s\n",
722d7467991SKishon Vijay Abraham I ret, root->cg_item.ci_namebuf);
723d7467991SKishon Vijay Abraham I goto err;
724d7467991SKishon Vijay Abraham I }
725d7467991SKishon Vijay Abraham I
726d7467991SKishon Vijay Abraham I functions_group = configfs_register_default_group(root, "functions",
727d7467991SKishon Vijay Abraham I &pci_functions_type);
728d7467991SKishon Vijay Abraham I if (IS_ERR(functions_group)) {
729d7467991SKishon Vijay Abraham I ret = PTR_ERR(functions_group);
730d7467991SKishon Vijay Abraham I pr_err("Error %d while registering functions group\n",
731d7467991SKishon Vijay Abraham I ret);
732d7467991SKishon Vijay Abraham I goto err_functions_group;
733d7467991SKishon Vijay Abraham I }
734d7467991SKishon Vijay Abraham I
735d7467991SKishon Vijay Abraham I controllers_group =
736d7467991SKishon Vijay Abraham I configfs_register_default_group(root, "controllers",
737d7467991SKishon Vijay Abraham I &pci_controllers_type);
738d7467991SKishon Vijay Abraham I if (IS_ERR(controllers_group)) {
739d7467991SKishon Vijay Abraham I ret = PTR_ERR(controllers_group);
740d7467991SKishon Vijay Abraham I pr_err("Error %d while registering controllers group\n",
741d7467991SKishon Vijay Abraham I ret);
742d7467991SKishon Vijay Abraham I goto err_controllers_group;
743d7467991SKishon Vijay Abraham I }
744d7467991SKishon Vijay Abraham I
745d7467991SKishon Vijay Abraham I return 0;
746d7467991SKishon Vijay Abraham I
747d7467991SKishon Vijay Abraham I err_controllers_group:
748d7467991SKishon Vijay Abraham I configfs_unregister_default_group(functions_group);
749d7467991SKishon Vijay Abraham I
750d7467991SKishon Vijay Abraham I err_functions_group:
751d7467991SKishon Vijay Abraham I configfs_unregister_subsystem(&pci_ep_cfs_subsys);
752d7467991SKishon Vijay Abraham I
753d7467991SKishon Vijay Abraham I err:
754d7467991SKishon Vijay Abraham I return ret;
755d7467991SKishon Vijay Abraham I }
756d7467991SKishon Vijay Abraham I module_init(pci_ep_cfs_init);
757d7467991SKishon Vijay Abraham I
pci_ep_cfs_exit(void)758d7467991SKishon Vijay Abraham I static void __exit pci_ep_cfs_exit(void)
759d7467991SKishon Vijay Abraham I {
760d7467991SKishon Vijay Abraham I configfs_unregister_default_group(controllers_group);
761d7467991SKishon Vijay Abraham I configfs_unregister_default_group(functions_group);
762d7467991SKishon Vijay Abraham I configfs_unregister_subsystem(&pci_ep_cfs_subsys);
763d7467991SKishon Vijay Abraham I }
764d7467991SKishon Vijay Abraham I module_exit(pci_ep_cfs_exit);
765d7467991SKishon Vijay Abraham I
766d7467991SKishon Vijay Abraham I MODULE_DESCRIPTION("PCI EP CONFIGFS");
767d7467991SKishon Vijay Abraham I MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
768