xref: /linux/drivers/pci/endpoint/pci-ep-cfs.c (revision c411ed854584a71b0e86ac3019b60e4789d88086)
1 /**
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 
27 static struct config_group *functions_group;
28 static struct config_group *controllers_group;
29 
30 struct pci_epf_group {
31 	struct config_group group;
32 	struct pci_epf *epf;
33 };
34 
35 struct pci_epc_group {
36 	struct config_group group;
37 	struct pci_epc *epc;
38 	bool start;
39 	unsigned long function_num_map;
40 };
41 
42 static 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 
47 static 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 
52 static 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 
82 static 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 
88 CONFIGFS_ATTR(pci_epc_, start);
89 
90 static struct configfs_attribute *pci_epc_attrs[] = {
91 	&pci_epc_attr_start,
92 	NULL,
93 };
94 
95 static 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_epc *epc;
101 	struct pci_epf *epf;
102 	struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
103 	struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
104 
105 	epc = epc_group->epc;
106 	epf = epf_group->epf;
107 	ret = pci_epc_add_epf(epc, epf);
108 	if (ret)
109 		goto err_add_epf;
110 
111 	func_no = find_first_zero_bit(&epc_group->function_num_map,
112 				      sizeof(epc_group->function_num_map));
113 	set_bit(func_no, &epc_group->function_num_map);
114 	epf->func_no = func_no;
115 
116 	ret = pci_epf_bind(epf);
117 	if (ret)
118 		goto err_epf_bind;
119 
120 	return 0;
121 
122 err_epf_bind:
123 	pci_epc_remove_epf(epc, epf);
124 
125 err_add_epf:
126 	clear_bit(func_no, &epc_group->function_num_map);
127 
128 	return ret;
129 }
130 
131 static void pci_epc_epf_unlink(struct config_item *epc_item,
132 			       struct config_item *epf_item)
133 {
134 	struct pci_epc *epc;
135 	struct pci_epf *epf;
136 	struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
137 	struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
138 
139 	WARN_ON_ONCE(epc_group->start);
140 
141 	epc = epc_group->epc;
142 	epf = epf_group->epf;
143 	clear_bit(epf->func_no, &epc_group->function_num_map);
144 	pci_epf_unbind(epf);
145 	pci_epc_remove_epf(epc, epf);
146 }
147 
148 static struct configfs_item_operations pci_epc_item_ops = {
149 	.allow_link	= pci_epc_epf_link,
150 	.drop_link	= pci_epc_epf_unlink,
151 };
152 
153 static struct config_item_type pci_epc_type = {
154 	.ct_item_ops	= &pci_epc_item_ops,
155 	.ct_attrs	= pci_epc_attrs,
156 	.ct_owner	= THIS_MODULE,
157 };
158 
159 struct config_group *pci_ep_cfs_add_epc_group(const char *name)
160 {
161 	int ret;
162 	struct pci_epc *epc;
163 	struct config_group *group;
164 	struct pci_epc_group *epc_group;
165 
166 	epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
167 	if (!epc_group) {
168 		ret = -ENOMEM;
169 		goto err;
170 	}
171 
172 	group = &epc_group->group;
173 
174 	config_group_init_type_name(group, name, &pci_epc_type);
175 	ret = configfs_register_group(controllers_group, group);
176 	if (ret) {
177 		pr_err("failed to register configfs group for %s\n", name);
178 		goto err_register_group;
179 	}
180 
181 	epc = pci_epc_get(name);
182 	if (IS_ERR(epc)) {
183 		ret = PTR_ERR(epc);
184 		goto err_epc_get;
185 	}
186 
187 	epc_group->epc = epc;
188 
189 	return group;
190 
191 err_epc_get:
192 	configfs_unregister_group(group);
193 
194 err_register_group:
195 	kfree(epc_group);
196 
197 err:
198 	return ERR_PTR(ret);
199 }
200 EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
201 
202 void pci_ep_cfs_remove_epc_group(struct config_group *group)
203 {
204 	struct pci_epc_group *epc_group;
205 
206 	if (!group)
207 		return;
208 
209 	epc_group = container_of(group, struct pci_epc_group, group);
210 	pci_epc_put(epc_group->epc);
211 	configfs_unregister_group(&epc_group->group);
212 	kfree(epc_group);
213 }
214 EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
215 
216 #define PCI_EPF_HEADER_R(_name)						       \
217 static ssize_t pci_epf_##_name##_show(struct config_item *item,	char *page)    \
218 {									       \
219 	struct pci_epf *epf = to_pci_epf_group(item)->epf;		       \
220 	if (WARN_ON_ONCE(!epf->header))					       \
221 		return -EINVAL;						       \
222 	return sprintf(page, "0x%04x\n", epf->header->_name);		       \
223 }
224 
225 #define PCI_EPF_HEADER_W_u32(_name)					       \
226 static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
227 				       const char *page, size_t len)	       \
228 {									       \
229 	u32 val;							       \
230 	int ret;							       \
231 	struct pci_epf *epf = to_pci_epf_group(item)->epf;		       \
232 	if (WARN_ON_ONCE(!epf->header))					       \
233 		return -EINVAL;						       \
234 	ret = kstrtou32(page, 0, &val);					       \
235 	if (ret)							       \
236 		return ret;						       \
237 	epf->header->_name = val;					       \
238 	return len;							       \
239 }
240 
241 #define PCI_EPF_HEADER_W_u16(_name)					       \
242 static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
243 				       const char *page, size_t len)	       \
244 {									       \
245 	u16 val;							       \
246 	int ret;							       \
247 	struct pci_epf *epf = to_pci_epf_group(item)->epf;		       \
248 	if (WARN_ON_ONCE(!epf->header))					       \
249 		return -EINVAL;						       \
250 	ret = kstrtou16(page, 0, &val);					       \
251 	if (ret)							       \
252 		return ret;						       \
253 	epf->header->_name = val;					       \
254 	return len;							       \
255 }
256 
257 #define PCI_EPF_HEADER_W_u8(_name)					       \
258 static ssize_t pci_epf_##_name##_store(struct config_item *item,	       \
259 				       const char *page, size_t len)	       \
260 {									       \
261 	u8 val;								       \
262 	int ret;							       \
263 	struct pci_epf *epf = to_pci_epf_group(item)->epf;		       \
264 	if (WARN_ON_ONCE(!epf->header))					       \
265 		return -EINVAL;						       \
266 	ret = kstrtou8(page, 0, &val);					       \
267 	if (ret)							       \
268 		return ret;						       \
269 	epf->header->_name = val;					       \
270 	return len;							       \
271 }
272 
273 static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
274 					    const char *page, size_t len)
275 {
276 	u8 val;
277 	int ret;
278 
279 	ret = kstrtou8(page, 0, &val);
280 	if (ret)
281 		return ret;
282 
283 	to_pci_epf_group(item)->epf->msi_interrupts = val;
284 
285 	return len;
286 }
287 
288 static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
289 					   char *page)
290 {
291 	return sprintf(page, "%d\n",
292 		       to_pci_epf_group(item)->epf->msi_interrupts);
293 }
294 
295 PCI_EPF_HEADER_R(vendorid)
296 PCI_EPF_HEADER_W_u16(vendorid)
297 
298 PCI_EPF_HEADER_R(deviceid)
299 PCI_EPF_HEADER_W_u16(deviceid)
300 
301 PCI_EPF_HEADER_R(revid)
302 PCI_EPF_HEADER_W_u8(revid)
303 
304 PCI_EPF_HEADER_R(progif_code)
305 PCI_EPF_HEADER_W_u8(progif_code)
306 
307 PCI_EPF_HEADER_R(subclass_code)
308 PCI_EPF_HEADER_W_u8(subclass_code)
309 
310 PCI_EPF_HEADER_R(baseclass_code)
311 PCI_EPF_HEADER_W_u8(baseclass_code)
312 
313 PCI_EPF_HEADER_R(cache_line_size)
314 PCI_EPF_HEADER_W_u8(cache_line_size)
315 
316 PCI_EPF_HEADER_R(subsys_vendor_id)
317 PCI_EPF_HEADER_W_u16(subsys_vendor_id)
318 
319 PCI_EPF_HEADER_R(subsys_id)
320 PCI_EPF_HEADER_W_u16(subsys_id)
321 
322 PCI_EPF_HEADER_R(interrupt_pin)
323 PCI_EPF_HEADER_W_u8(interrupt_pin)
324 
325 CONFIGFS_ATTR(pci_epf_, vendorid);
326 CONFIGFS_ATTR(pci_epf_, deviceid);
327 CONFIGFS_ATTR(pci_epf_, revid);
328 CONFIGFS_ATTR(pci_epf_, progif_code);
329 CONFIGFS_ATTR(pci_epf_, subclass_code);
330 CONFIGFS_ATTR(pci_epf_, baseclass_code);
331 CONFIGFS_ATTR(pci_epf_, cache_line_size);
332 CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
333 CONFIGFS_ATTR(pci_epf_, subsys_id);
334 CONFIGFS_ATTR(pci_epf_, interrupt_pin);
335 CONFIGFS_ATTR(pci_epf_, msi_interrupts);
336 
337 static struct configfs_attribute *pci_epf_attrs[] = {
338 	&pci_epf_attr_vendorid,
339 	&pci_epf_attr_deviceid,
340 	&pci_epf_attr_revid,
341 	&pci_epf_attr_progif_code,
342 	&pci_epf_attr_subclass_code,
343 	&pci_epf_attr_baseclass_code,
344 	&pci_epf_attr_cache_line_size,
345 	&pci_epf_attr_subsys_vendor_id,
346 	&pci_epf_attr_subsys_id,
347 	&pci_epf_attr_interrupt_pin,
348 	&pci_epf_attr_msi_interrupts,
349 	NULL,
350 };
351 
352 static void pci_epf_release(struct config_item *item)
353 {
354 	struct pci_epf_group *epf_group = to_pci_epf_group(item);
355 
356 	pci_epf_destroy(epf_group->epf);
357 	kfree(epf_group);
358 }
359 
360 static struct configfs_item_operations pci_epf_ops = {
361 	.release		= pci_epf_release,
362 };
363 
364 static struct config_item_type pci_epf_type = {
365 	.ct_item_ops	= &pci_epf_ops,
366 	.ct_attrs	= pci_epf_attrs,
367 	.ct_owner	= THIS_MODULE,
368 };
369 
370 static struct config_group *pci_epf_make(struct config_group *group,
371 					 const char *name)
372 {
373 	struct pci_epf_group *epf_group;
374 	struct pci_epf *epf;
375 
376 	epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
377 	if (!epf_group)
378 		return ERR_PTR(-ENOMEM);
379 
380 	config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
381 
382 	epf = pci_epf_create(group->cg_item.ci_name);
383 	if (IS_ERR(epf)) {
384 		pr_err("failed to create endpoint function device\n");
385 		return ERR_PTR(-EINVAL);
386 	}
387 
388 	epf_group->epf = epf;
389 
390 	return &epf_group->group;
391 }
392 
393 static void pci_epf_drop(struct config_group *group, struct config_item *item)
394 {
395 	config_item_put(item);
396 }
397 
398 static struct configfs_group_operations pci_epf_group_ops = {
399 	.make_group     = &pci_epf_make,
400 	.drop_item      = &pci_epf_drop,
401 };
402 
403 static struct config_item_type pci_epf_group_type = {
404 	.ct_group_ops	= &pci_epf_group_ops,
405 	.ct_owner	= THIS_MODULE,
406 };
407 
408 struct config_group *pci_ep_cfs_add_epf_group(const char *name)
409 {
410 	struct config_group *group;
411 
412 	group = configfs_register_default_group(functions_group, name,
413 						&pci_epf_group_type);
414 	if (IS_ERR(group))
415 		pr_err("failed to register configfs group for %s function\n",
416 		       name);
417 
418 	return group;
419 }
420 EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
421 
422 void pci_ep_cfs_remove_epf_group(struct config_group *group)
423 {
424 	if (IS_ERR_OR_NULL(group))
425 		return;
426 
427 	configfs_unregister_default_group(group);
428 }
429 EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
430 
431 static struct config_item_type pci_functions_type = {
432 	.ct_owner	= THIS_MODULE,
433 };
434 
435 static struct config_item_type pci_controllers_type = {
436 	.ct_owner	= THIS_MODULE,
437 };
438 
439 static struct config_item_type pci_ep_type = {
440 	.ct_owner	= THIS_MODULE,
441 };
442 
443 static struct configfs_subsystem pci_ep_cfs_subsys = {
444 	.su_group = {
445 		.cg_item = {
446 			.ci_namebuf = "pci_ep",
447 			.ci_type = &pci_ep_type,
448 		},
449 	},
450 	.su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
451 };
452 
453 static int __init pci_ep_cfs_init(void)
454 {
455 	int ret;
456 	struct config_group *root = &pci_ep_cfs_subsys.su_group;
457 
458 	config_group_init(root);
459 
460 	ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
461 	if (ret) {
462 		pr_err("Error %d while registering subsystem %s\n",
463 		       ret, root->cg_item.ci_namebuf);
464 		goto err;
465 	}
466 
467 	functions_group = configfs_register_default_group(root, "functions",
468 							  &pci_functions_type);
469 	if (IS_ERR(functions_group)) {
470 		ret = PTR_ERR(functions_group);
471 		pr_err("Error %d while registering functions group\n",
472 		       ret);
473 		goto err_functions_group;
474 	}
475 
476 	controllers_group =
477 		configfs_register_default_group(root, "controllers",
478 						&pci_controllers_type);
479 	if (IS_ERR(controllers_group)) {
480 		ret = PTR_ERR(controllers_group);
481 		pr_err("Error %d while registering controllers group\n",
482 		       ret);
483 		goto err_controllers_group;
484 	}
485 
486 	return 0;
487 
488 err_controllers_group:
489 	configfs_unregister_default_group(functions_group);
490 
491 err_functions_group:
492 	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
493 
494 err:
495 	return ret;
496 }
497 module_init(pci_ep_cfs_init);
498 
499 static void __exit pci_ep_cfs_exit(void)
500 {
501 	configfs_unregister_default_group(controllers_group);
502 	configfs_unregister_default_group(functions_group);
503 	configfs_unregister_subsystem(&pci_ep_cfs_subsys);
504 }
505 module_exit(pci_ep_cfs_exit);
506 
507 MODULE_DESCRIPTION("PCI EP CONFIGFS");
508 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
509 MODULE_LICENSE("GPL v2");
510