Merge tag 'for-linus-20160801' of git://git.infradead.org/linux-mtd
[deliverable/linux.git] / drivers / usb / usbip / vudc_main.c
CommitLineData
80fd9cd5
IK
1/*
2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
3 * Copyright (C) 2015-2016 Samsung Electronics
4 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
5 * Krzysztof Opasiak <k.opasiak@samsung.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 as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/device.h>
22#include <linux/list.h>
23#include <linux/module.h>
24
25#include "vudc.h"
26
27static unsigned int vudc_number = 1;
28
29module_param_named(num, vudc_number, uint, S_IRUGO);
30MODULE_PARM_DESC(num, "number of emulated controllers");
31
32static struct platform_driver vudc_driver = {
33 .probe = vudc_probe,
34 .remove = vudc_remove,
35 .driver = {
36 .name = GADGET_NAME,
37 },
38};
39
40static struct list_head vudc_devices = LIST_HEAD_INIT(vudc_devices);
41
42static int __init init(void)
43{
44 int retval = -ENOMEM;
45 int i;
46 struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL;
47
48 if (usb_disabled())
49 return -ENODEV;
50
51 if (vudc_number < 1) {
52 pr_err("Number of emulated UDC must be no less than 1");
53 return -EINVAL;
54 }
55
56 retval = platform_driver_register(&vudc_driver);
57 if (retval < 0)
58 goto out;
59
60 for (i = 0; i < vudc_number; i++) {
61 udc_dev = alloc_vudc_device(i);
62 if (!udc_dev) {
63 retval = -ENOMEM;
64 goto cleanup;
65 }
66
67 retval = platform_device_add(udc_dev->pdev);
68 if (retval < 0) {
69 put_vudc_device(udc_dev);
70 goto cleanup;
71 }
72
73 list_add_tail(&udc_dev->dev_entry, &vudc_devices);
74 if (!platform_get_drvdata(udc_dev->pdev)) {
75 /*
76 * The udc was added successfully but its probe
77 * function failed for some reason.
78 */
79 retval = -EINVAL;
80 goto cleanup;
81 }
82 }
83 goto out;
84
85cleanup:
86 list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) {
87 list_del(&udc_dev->dev_entry);
88 platform_device_del(udc_dev->pdev);
89 put_vudc_device(udc_dev);
90 }
91
92 platform_driver_unregister(&vudc_driver);
93out:
94 return retval;
95}
96module_init(init);
97
98static void __exit cleanup(void)
99{
100 struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL;
101
102 list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) {
103 list_del(&udc_dev->dev_entry);
104 platform_device_unregister(udc_dev->pdev);
105 put_vudc_device(udc_dev);
106 }
107 platform_driver_unregister(&vudc_driver);
108}
109module_exit(cleanup);
110
111MODULE_DESCRIPTION("USB over IP Device Controller");
112MODULE_AUTHOR("Krzysztof Opasiak, Karol Kosik, Igor Kotrasinski");
113MODULE_LICENSE("GPL");
This page took 0.046417 seconds and 5 git commands to generate.