1 | /* |
2 | * Intel MIC Platform Software Stack (MPSS) |
3 | * |
4 | * Copyright(c) 2015 Intel Corporation. |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License, version 2, as |
8 | * published by the Free Software Foundation. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, but |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * General Public License for more details. |
14 | * |
15 | * The full GNU General Public License is included in this distribution in |
16 | * the file called "COPYING". |
17 | * |
18 | * Intel MIC COSM Bus Driver |
19 | */ |
20 | #include <linux/slab.h> |
21 | #include <linux/module.h> |
22 | #include <linux/idr.h> |
23 | #include "cosm_bus.h" |
24 | |
25 | /* Unique numbering for cosm devices. */ |
26 | static DEFINE_IDA(cosm_index_ida); |
27 | |
28 | static int cosm_dev_probe(struct device *d) |
29 | { |
30 | struct cosm_device *dev = dev_to_cosm(d); |
31 | struct cosm_driver *drv = drv_to_cosm(dev->dev.driver); |
32 | |
33 | return drv->probe(dev); |
34 | } |
35 | |
36 | static int cosm_dev_remove(struct device *d) |
37 | { |
38 | struct cosm_device *dev = dev_to_cosm(d); |
39 | struct cosm_driver *drv = drv_to_cosm(dev->dev.driver); |
40 | |
41 | drv->remove(dev); |
42 | return 0; |
43 | } |
44 | |
45 | static struct bus_type cosm_bus = { |
46 | .name = "cosm_bus" , |
47 | .probe = cosm_dev_probe, |
48 | .remove = cosm_dev_remove, |
49 | }; |
50 | |
51 | int cosm_register_driver(struct cosm_driver *driver) |
52 | { |
53 | driver->driver.bus = &cosm_bus; |
54 | return driver_register(&driver->driver); |
55 | } |
56 | EXPORT_SYMBOL_GPL(cosm_register_driver); |
57 | |
58 | void cosm_unregister_driver(struct cosm_driver *driver) |
59 | { |
60 | driver_unregister(&driver->driver); |
61 | } |
62 | EXPORT_SYMBOL_GPL(cosm_unregister_driver); |
63 | |
64 | static inline void cosm_release_dev(struct device *d) |
65 | { |
66 | struct cosm_device *cdev = dev_to_cosm(d); |
67 | |
68 | kfree(cdev); |
69 | } |
70 | |
71 | struct cosm_device * |
72 | cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops) |
73 | { |
74 | struct cosm_device *cdev; |
75 | int ret; |
76 | |
77 | cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); |
78 | if (!cdev) |
79 | return ERR_PTR(-ENOMEM); |
80 | |
81 | cdev->dev.parent = pdev; |
82 | cdev->dev.release = cosm_release_dev; |
83 | cdev->hw_ops = hw_ops; |
84 | dev_set_drvdata(&cdev->dev, cdev); |
85 | cdev->dev.bus = &cosm_bus; |
86 | |
87 | /* Assign a unique device index and hence name */ |
88 | ret = ida_simple_get(&cosm_index_ida, 0, 0, GFP_KERNEL); |
89 | if (ret < 0) |
90 | goto free_cdev; |
91 | |
92 | cdev->index = ret; |
93 | cdev->dev.id = ret; |
94 | dev_set_name(&cdev->dev, "cosm-dev%u" , cdev->index); |
95 | |
96 | ret = device_register(&cdev->dev); |
97 | if (ret) |
98 | goto ida_remove; |
99 | return cdev; |
100 | ida_remove: |
101 | ida_simple_remove(&cosm_index_ida, cdev->index); |
102 | free_cdev: |
103 | put_device(&cdev->dev); |
104 | return ERR_PTR(ret); |
105 | } |
106 | EXPORT_SYMBOL_GPL(cosm_register_device); |
107 | |
108 | void cosm_unregister_device(struct cosm_device *dev) |
109 | { |
110 | int index = dev->index; /* save for after device release */ |
111 | |
112 | device_unregister(&dev->dev); |
113 | ida_simple_remove(&cosm_index_ida, index); |
114 | } |
115 | EXPORT_SYMBOL_GPL(cosm_unregister_device); |
116 | |
117 | struct cosm_device *cosm_find_cdev_by_id(int id) |
118 | { |
119 | struct device *dev = subsys_find_device_by_id(&cosm_bus, id, NULL); |
120 | |
121 | return dev ? container_of(dev, struct cosm_device, dev) : NULL; |
122 | } |
123 | EXPORT_SYMBOL_GPL(cosm_find_cdev_by_id); |
124 | |
125 | static int __init cosm_init(void) |
126 | { |
127 | return bus_register(&cosm_bus); |
128 | } |
129 | |
130 | static void __exit cosm_exit(void) |
131 | { |
132 | bus_unregister(&cosm_bus); |
133 | ida_destroy(&cosm_index_ida); |
134 | } |
135 | |
136 | core_initcall(cosm_init); |
137 | module_exit(cosm_exit); |
138 | |
139 | MODULE_AUTHOR("Intel Corporation" ); |
140 | MODULE_DESCRIPTION("Intel(R) MIC card OS state management bus driver" ); |
141 | MODULE_LICENSE("GPL v2" ); |
142 | |