6
6
#include <linux/device.h>
7
7
#include <linux/idr.h>
8
8
#include <linux/kernel.h>
9
+ #include <linux/list.h>
10
+ #include <linux/mutex.h>
9
11
#include <linux/rtnetlink.h>
10
12
#include <linux/slab.h>
11
13
#include <linux/sysfs.h>
12
14
13
15
#include "netdevsim.h"
14
16
15
17
static DEFINE_IDA (nsim_bus_dev_ids );
18
+ static LIST_HEAD (nsim_bus_dev_list );
19
+ static DEFINE_MUTEX (nsim_bus_dev_list_lock );
16
20
17
21
static struct nsim_bus_dev * to_nsim_bus_dev (struct device * dev )
18
22
{
@@ -113,6 +117,83 @@ static struct device_type nsim_bus_dev_type = {
113
117
.release = nsim_bus_dev_release ,
114
118
};
115
119
120
+ static ssize_t
121
+ new_device_store (struct bus_type * bus , const char * buf , size_t count )
122
+ {
123
+ struct nsim_bus_dev * nsim_bus_dev ;
124
+ unsigned int port_count ;
125
+ unsigned int id ;
126
+ int err ;
127
+
128
+ err = sscanf (buf , "%u %u" , & id , & port_count );
129
+ switch (err ) {
130
+ case 1 :
131
+ port_count = 1 ;
132
+ /* pass through */
133
+ case 2 :
134
+ if (id > INT_MAX ) {
135
+ pr_err ("Value of \"id\" is too big.\n" );
136
+ return - EINVAL ;
137
+ }
138
+ break ;
139
+ default :
140
+ pr_err ("Format for adding new device is \"id port_count\" (uint uint).\n" );
141
+ return - EINVAL ;
142
+ }
143
+ nsim_bus_dev = nsim_bus_dev_new (id , port_count );
144
+ if (IS_ERR (nsim_bus_dev ))
145
+ return PTR_ERR (nsim_bus_dev );
146
+
147
+ mutex_lock (& nsim_bus_dev_list_lock );
148
+ list_add_tail (& nsim_bus_dev -> list , & nsim_bus_dev_list );
149
+ mutex_unlock (& nsim_bus_dev_list_lock );
150
+
151
+ return count ;
152
+ }
153
+ static BUS_ATTR_WO (new_device );
154
+
155
+ static ssize_t
156
+ del_device_store (struct bus_type * bus , const char * buf , size_t count )
157
+ {
158
+ struct nsim_bus_dev * nsim_bus_dev , * tmp ;
159
+ unsigned int id ;
160
+ int err ;
161
+
162
+ err = sscanf (buf , "%u" , & id );
163
+ switch (err ) {
164
+ case 1 :
165
+ if (id > INT_MAX ) {
166
+ pr_err ("Value of \"id\" is too big.\n" );
167
+ return - EINVAL ;
168
+ }
169
+ break ;
170
+ default :
171
+ pr_err ("Format for deleting device is \"id\" (uint).\n" );
172
+ return - EINVAL ;
173
+ }
174
+
175
+ err = - ENOENT ;
176
+ mutex_lock (& nsim_bus_dev_list_lock );
177
+ list_for_each_entry_safe (nsim_bus_dev , tmp , & nsim_bus_dev_list , list ) {
178
+ if (nsim_bus_dev -> dev .id != id )
179
+ continue ;
180
+ list_del (& nsim_bus_dev -> list );
181
+ nsim_bus_dev_del (nsim_bus_dev );
182
+ err = 0 ;
183
+ break ;
184
+ }
185
+ mutex_unlock (& nsim_bus_dev_list_lock );
186
+ return !err ? count : err ;
187
+ }
188
+ static BUS_ATTR_WO (del_device );
189
+
190
+ static struct attribute * nsim_bus_attrs [] = {
191
+ & bus_attr_new_device .attr ,
192
+ & bus_attr_del_device .attr ,
193
+ NULL
194
+ };
195
+ ATTRIBUTE_GROUPS (nsim_bus );
196
+
116
197
int nsim_num_vf (struct device * dev )
117
198
{
118
199
struct nsim_bus_dev * nsim_bus_dev = to_nsim_bus_dev (dev );
@@ -123,10 +204,11 @@ int nsim_num_vf(struct device *dev)
123
204
static struct bus_type nsim_bus = {
124
205
.name = DRV_NAME ,
125
206
.dev_name = DRV_NAME ,
207
+ .bus_groups = nsim_bus_groups ,
126
208
.num_vf = nsim_num_vf ,
127
209
};
128
210
129
- struct nsim_bus_dev * nsim_bus_dev_new (void )
211
+ struct nsim_bus_dev * nsim_bus_dev_new (unsigned int id , unsigned int port_count )
130
212
{
131
213
struct nsim_bus_dev * nsim_bus_dev ;
132
214
int err ;
@@ -135,12 +217,15 @@ struct nsim_bus_dev *nsim_bus_dev_new(void)
135
217
if (!nsim_bus_dev )
136
218
return ERR_PTR (- ENOMEM );
137
219
138
- err = ida_alloc (& nsim_bus_dev_ids , GFP_KERNEL );
220
+ err = ida_alloc_range (& nsim_bus_dev_ids ,
221
+ id == ~0 ? 0 : id , id , GFP_KERNEL );
139
222
if (err < 0 )
140
223
goto err_nsim_bus_dev_free ;
141
224
nsim_bus_dev -> dev .id = err ;
142
225
nsim_bus_dev -> dev .bus = & nsim_bus ;
143
226
nsim_bus_dev -> dev .type = & nsim_bus_dev_type ;
227
+ nsim_bus_dev -> port_count = port_count ;
228
+
144
229
err = device_register (& nsim_bus_dev -> dev );
145
230
if (err )
146
231
goto err_nsim_bus_dev_id_free ;
@@ -185,6 +270,14 @@ int nsim_bus_init(void)
185
270
186
271
void nsim_bus_exit (void )
187
272
{
273
+ struct nsim_bus_dev * nsim_bus_dev , * tmp ;
274
+
275
+ mutex_lock (& nsim_bus_dev_list_lock );
276
+ list_for_each_entry_safe (nsim_bus_dev , tmp , & nsim_bus_dev_list , list ) {
277
+ list_del (& nsim_bus_dev -> list );
278
+ nsim_bus_dev_del (nsim_bus_dev );
279
+ }
280
+ mutex_unlock (& nsim_bus_dev_list_lock );
188
281
driver_unregister (& nsim_driver );
189
282
bus_unregister (& nsim_bus );
190
283
}
0 commit comments