blob: 8fdb9d07c50a9a6834a9cd45b226bab335376b6f [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/**
2 * configfs to configure the PCI endpoint
3 *
4 * Copyright (C) 2017 Texas Instruments
5 * Author: Kishon Vijay Abraham I <kishon@ti.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 of
9 * the License as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/module.h>
21#include <linux/slab.h>
22
23#include <linux/pci-epc.h>
24#include <linux/pci-epf.h>
25#include <linux/pci-ep-cfs.h>
26
27static struct config_group *functions_group;
28static struct config_group *controllers_group;
29
30struct pci_epf_group {
31 struct config_group group;
32 struct pci_epf *epf;
33};
34
35struct pci_epc_group {
36 struct config_group group;
37 struct pci_epc *epc;
38 bool start;
39 unsigned long function_num_map;
40};
41
42static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
43{
44 return container_of(to_config_group(item), struct pci_epf_group, group);
45}
46
47static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
48{
49 return container_of(to_config_group(item), struct pci_epc_group, group);
50}
51
52static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
53 size_t len)
54{
55 int ret;
56 bool start;
57 struct pci_epc *epc;
58 struct pci_epc_group *epc_group = to_pci_epc_group(item);
59
60 epc = epc_group->epc;
61
62 ret = kstrtobool(page, &start);
63 if (ret)
64 return ret;
65
66 if (!start) {
67 pci_epc_stop(epc);
68 return len;
69 }
70
71 ret = pci_epc_start(epc);
72 if (ret) {
73 dev_err(&epc->dev, "failed to start endpoint controller\n");
74 return -EINVAL;
75 }
76
77 epc_group->start = start;
78
79 return len;
80}
81
82static ssize_t pci_epc_start_show(struct config_item *item, char *page)
83{
84 return sprintf(page, "%d\n",
85 to_pci_epc_group(item)->start);
86}
87
88CONFIGFS_ATTR(pci_epc_, start);
89
90static struct configfs_attribute *pci_epc_attrs[] = {
91 &pci_epc_attr_start,
92 NULL,
93};
94
95static int pci_epc_epf_link(struct config_item *epc_item,
96 struct config_item *epf_item)
97{
98 int ret;
99 u32 func_no = 0;
100 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
101 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
102 struct pci_epc *epc = epc_group->epc;
103 struct pci_epf *epf = epf_group->epf;
104
105 func_no = find_first_zero_bit(&epc_group->function_num_map,
106 BITS_PER_LONG);
107 if (func_no >= BITS_PER_LONG)
108 return -EINVAL;
109
110 set_bit(func_no, &epc_group->function_num_map);
111 epf->func_no = func_no;
112
113 ret = pci_epc_add_epf(epc, epf);
114 if (ret)
115 goto err_add_epf;
116
117 ret = pci_epf_bind(epf);
118 if (ret)
119 goto err_epf_bind;
120
121 return 0;
122
123err_epf_bind:
124 pci_epc_remove_epf(epc, epf);
125
126err_add_epf:
127 clear_bit(func_no, &epc_group->function_num_map);
128
129 return ret;
130}
131
132static void pci_epc_epf_unlink(struct config_item *epc_item,
133 struct config_item *epf_item)
134{
135 struct pci_epc *epc;
136 struct pci_epf *epf;
137 struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
138 struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
139
140 WARN_ON_ONCE(epc_group->start);
141
142 epc = epc_group->epc;
143 epf = epf_group->epf;
144 clear_bit(epf->func_no, &epc_group->function_num_map);
145 pci_epf_unbind(epf);
146 pci_epc_remove_epf(epc, epf);
147}
148
149static struct configfs_item_operations pci_epc_item_ops = {
150 .allow_link = pci_epc_epf_link,
151 .drop_link = pci_epc_epf_unlink,
152};
153
154static struct config_item_type pci_epc_type = {
155 .ct_item_ops = &pci_epc_item_ops,
156 .ct_attrs = pci_epc_attrs,
157 .ct_owner = THIS_MODULE,
158};
159
160struct config_group *pci_ep_cfs_add_epc_group(const char *name)
161{
162 int ret;
163 struct pci_epc *epc;
164 struct config_group *group;
165 struct pci_epc_group *epc_group;
166
167 epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
168 if (!epc_group) {
169 ret = -ENOMEM;
170 goto err;
171 }
172
173 group = &epc_group->group;
174
175 config_group_init_type_name(group, name, &pci_epc_type);
176 ret = configfs_register_group(controllers_group, group);
177 if (ret) {
178 pr_err("failed to register configfs group for %s\n", name);
179 goto err_register_group;
180 }
181
182 epc = pci_epc_get(name);
183 if (IS_ERR(epc)) {
184 ret = PTR_ERR(epc);
185 goto err_epc_get;
186 }
187
188 epc_group->epc = epc;
189
190 return group;
191
192err_epc_get:
193 configfs_unregister_group(group);
194
195err_register_group:
196 kfree(epc_group);
197
198err:
199 return ERR_PTR(ret);
200}
201EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
202
203void pci_ep_cfs_remove_epc_group(struct config_group *group)
204{
205 struct pci_epc_group *epc_group;
206
207 if (!group)
208 return;
209
210 epc_group = container_of(group, struct pci_epc_group, group);
211 pci_epc_put(epc_group->epc);
212 configfs_unregister_group(&epc_group->group);
213 kfree(epc_group);
214}
215EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
216
217#define PCI_EPF_HEADER_R(_name) \
218static ssize_t pci_epf_##_name##_show(struct config_item *item, char *page) \
219{ \
220 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
221 if (WARN_ON_ONCE(!epf->header)) \
222 return -EINVAL; \
223 return sprintf(page, "0x%04x\n", epf->header->_name); \
224}
225
226#define PCI_EPF_HEADER_W_u32(_name) \
227static ssize_t pci_epf_##_name##_store(struct config_item *item, \
228 const char *page, size_t len) \
229{ \
230 u32 val; \
231 int ret; \
232 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
233 if (WARN_ON_ONCE(!epf->header)) \
234 return -EINVAL; \
235 ret = kstrtou32(page, 0, &val); \
236 if (ret) \
237 return ret; \
238 epf->header->_name = val; \
239 return len; \
240}
241
242#define PCI_EPF_HEADER_W_u16(_name) \
243static ssize_t pci_epf_##_name##_store(struct config_item *item, \
244 const char *page, size_t len) \
245{ \
246 u16 val; \
247 int ret; \
248 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
249 if (WARN_ON_ONCE(!epf->header)) \
250 return -EINVAL; \
251 ret = kstrtou16(page, 0, &val); \
252 if (ret) \
253 return ret; \
254 epf->header->_name = val; \
255 return len; \
256}
257
258#define PCI_EPF_HEADER_W_u8(_name) \
259static ssize_t pci_epf_##_name##_store(struct config_item *item, \
260 const char *page, size_t len) \
261{ \
262 u8 val; \
263 int ret; \
264 struct pci_epf *epf = to_pci_epf_group(item)->epf; \
265 if (WARN_ON_ONCE(!epf->header)) \
266 return -EINVAL; \
267 ret = kstrtou8(page, 0, &val); \
268 if (ret) \
269 return ret; \
270 epf->header->_name = val; \
271 return len; \
272}
273
274static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
275 const char *page, size_t len)
276{
277 u8 val;
278 int ret;
279
280 ret = kstrtou8(page, 0, &val);
281 if (ret)
282 return ret;
283
284 to_pci_epf_group(item)->epf->msi_interrupts = val;
285
286 return len;
287}
288
289static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
290 char *page)
291{
292 return sprintf(page, "%d\n",
293 to_pci_epf_group(item)->epf->msi_interrupts);
294}
295
296PCI_EPF_HEADER_R(vendorid)
297PCI_EPF_HEADER_W_u16(vendorid)
298
299PCI_EPF_HEADER_R(deviceid)
300PCI_EPF_HEADER_W_u16(deviceid)
301
302PCI_EPF_HEADER_R(revid)
303PCI_EPF_HEADER_W_u8(revid)
304
305PCI_EPF_HEADER_R(progif_code)
306PCI_EPF_HEADER_W_u8(progif_code)
307
308PCI_EPF_HEADER_R(subclass_code)
309PCI_EPF_HEADER_W_u8(subclass_code)
310
311PCI_EPF_HEADER_R(baseclass_code)
312PCI_EPF_HEADER_W_u8(baseclass_code)
313
314PCI_EPF_HEADER_R(cache_line_size)
315PCI_EPF_HEADER_W_u8(cache_line_size)
316
317PCI_EPF_HEADER_R(subsys_vendor_id)
318PCI_EPF_HEADER_W_u16(subsys_vendor_id)
319
320PCI_EPF_HEADER_R(subsys_id)
321PCI_EPF_HEADER_W_u16(subsys_id)
322
323PCI_EPF_HEADER_R(interrupt_pin)
324PCI_EPF_HEADER_W_u8(interrupt_pin)
325
326CONFIGFS_ATTR(pci_epf_, vendorid);
327CONFIGFS_ATTR(pci_epf_, deviceid);
328CONFIGFS_ATTR(pci_epf_, revid);
329CONFIGFS_ATTR(pci_epf_, progif_code);
330CONFIGFS_ATTR(pci_epf_, subclass_code);
331CONFIGFS_ATTR(pci_epf_, baseclass_code);
332CONFIGFS_ATTR(pci_epf_, cache_line_size);
333CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
334CONFIGFS_ATTR(pci_epf_, subsys_id);
335CONFIGFS_ATTR(pci_epf_, interrupt_pin);
336CONFIGFS_ATTR(pci_epf_, msi_interrupts);
337
338static struct configfs_attribute *pci_epf_attrs[] = {
339 &pci_epf_attr_vendorid,
340 &pci_epf_attr_deviceid,
341 &pci_epf_attr_revid,
342 &pci_epf_attr_progif_code,
343 &pci_epf_attr_subclass_code,
344 &pci_epf_attr_baseclass_code,
345 &pci_epf_attr_cache_line_size,
346 &pci_epf_attr_subsys_vendor_id,
347 &pci_epf_attr_subsys_id,
348 &pci_epf_attr_interrupt_pin,
349 &pci_epf_attr_msi_interrupts,
350 NULL,
351};
352
353static void pci_epf_release(struct config_item *item)
354{
355 struct pci_epf_group *epf_group = to_pci_epf_group(item);
356
357 pci_epf_destroy(epf_group->epf);
358 kfree(epf_group);
359}
360
361static struct configfs_item_operations pci_epf_ops = {
362 .release = pci_epf_release,
363};
364
365static struct config_item_type pci_epf_type = {
366 .ct_item_ops = &pci_epf_ops,
367 .ct_attrs = pci_epf_attrs,
368 .ct_owner = THIS_MODULE,
369};
370
371static struct config_group *pci_epf_make(struct config_group *group,
372 const char *name)
373{
374 struct pci_epf_group *epf_group;
375 struct pci_epf *epf;
376
377 epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
378 if (!epf_group)
379 return ERR_PTR(-ENOMEM);
380
381 config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
382
383 epf = pci_epf_create(group->cg_item.ci_name);
384 if (IS_ERR(epf)) {
385 pr_err("failed to create endpoint function device\n");
386 return ERR_PTR(-EINVAL);
387 }
388
389 epf_group->epf = epf;
390
391 return &epf_group->group;
392}
393
394static void pci_epf_drop(struct config_group *group, struct config_item *item)
395{
396 config_item_put(item);
397}
398
399static struct configfs_group_operations pci_epf_group_ops = {
400 .make_group = &pci_epf_make,
401 .drop_item = &pci_epf_drop,
402};
403
404static struct config_item_type pci_epf_group_type = {
405 .ct_group_ops = &pci_epf_group_ops,
406 .ct_owner = THIS_MODULE,
407};
408
409struct config_group *pci_ep_cfs_add_epf_group(const char *name)
410{
411 struct config_group *group;
412
413 group = configfs_register_default_group(functions_group, name,
414 &pci_epf_group_type);
415 if (IS_ERR(group))
416 pr_err("failed to register configfs group for %s function\n",
417 name);
418
419 return group;
420}
421EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
422
423void pci_ep_cfs_remove_epf_group(struct config_group *group)
424{
425 if (IS_ERR_OR_NULL(group))
426 return;
427
428 configfs_unregister_default_group(group);
429}
430EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
431
432static struct config_item_type pci_functions_type = {
433 .ct_owner = THIS_MODULE,
434};
435
436static struct config_item_type pci_controllers_type = {
437 .ct_owner = THIS_MODULE,
438};
439
440static struct config_item_type pci_ep_type = {
441 .ct_owner = THIS_MODULE,
442};
443
444static struct configfs_subsystem pci_ep_cfs_subsys = {
445 .su_group = {
446 .cg_item = {
447 .ci_namebuf = "pci_ep",
448 .ci_type = &pci_ep_type,
449 },
450 },
451 .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
452};
453
454static int __init pci_ep_cfs_init(void)
455{
456 int ret;
457 struct config_group *root = &pci_ep_cfs_subsys.su_group;
458
459 config_group_init(root);
460
461 ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
462 if (ret) {
463 pr_err("Error %d while registering subsystem %s\n",
464 ret, root->cg_item.ci_namebuf);
465 goto err;
466 }
467
468 functions_group = configfs_register_default_group(root, "functions",
469 &pci_functions_type);
470 if (IS_ERR(functions_group)) {
471 ret = PTR_ERR(functions_group);
472 pr_err("Error %d while registering functions group\n",
473 ret);
474 goto err_functions_group;
475 }
476
477 controllers_group =
478 configfs_register_default_group(root, "controllers",
479 &pci_controllers_type);
480 if (IS_ERR(controllers_group)) {
481 ret = PTR_ERR(controllers_group);
482 pr_err("Error %d while registering controllers group\n",
483 ret);
484 goto err_controllers_group;
485 }
486
487 return 0;
488
489err_controllers_group:
490 configfs_unregister_default_group(functions_group);
491
492err_functions_group:
493 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
494
495err:
496 return ret;
497}
498module_init(pci_ep_cfs_init);
499
500static void __exit pci_ep_cfs_exit(void)
501{
502 configfs_unregister_default_group(controllers_group);
503 configfs_unregister_default_group(functions_group);
504 configfs_unregister_subsystem(&pci_ep_cfs_subsys);
505}
506module_exit(pci_ep_cfs_exit);
507
508MODULE_DESCRIPTION("PCI EP CONFIGFS");
509MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
510MODULE_LICENSE("GPL v2");