66#include <linux/device.h>
77#include <linux/idr.h>
88#include <linux/kernel.h>
9+ #include <linux/list.h>
10+ #include <linux/mutex.h>
911#include <linux/rtnetlink.h>
1012#include <linux/slab.h>
1113#include <linux/sysfs.h>
1214
1315#include "netdevsim.h"
1416
1517static DEFINE_IDA (nsim_bus_dev_ids );
18+ static LIST_HEAD (nsim_bus_dev_list );
19+ static DEFINE_MUTEX (nsim_bus_dev_list_lock );
1620
1721static struct nsim_bus_dev * to_nsim_bus_dev (struct device * dev )
1822{
@@ -113,6 +117,83 @@ static struct device_type nsim_bus_dev_type = {
113117 .release = nsim_bus_dev_release ,
114118};
115119
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+
116197int nsim_num_vf (struct device * dev )
117198{
118199 struct nsim_bus_dev * nsim_bus_dev = to_nsim_bus_dev (dev );
@@ -123,10 +204,11 @@ int nsim_num_vf(struct device *dev)
123204static struct bus_type nsim_bus = {
124205 .name = DRV_NAME ,
125206 .dev_name = DRV_NAME ,
207+ .bus_groups = nsim_bus_groups ,
126208 .num_vf = nsim_num_vf ,
127209};
128210
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 )
130212{
131213 struct nsim_bus_dev * nsim_bus_dev ;
132214 int err ;
@@ -135,12 +217,15 @@ struct nsim_bus_dev *nsim_bus_dev_new(void)
135217 if (!nsim_bus_dev )
136218 return ERR_PTR (- ENOMEM );
137219
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 );
139222 if (err < 0 )
140223 goto err_nsim_bus_dev_free ;
141224 nsim_bus_dev -> dev .id = err ;
142225 nsim_bus_dev -> dev .bus = & nsim_bus ;
143226 nsim_bus_dev -> dev .type = & nsim_bus_dev_type ;
227+ nsim_bus_dev -> port_count = port_count ;
228+
144229 err = device_register (& nsim_bus_dev -> dev );
145230 if (err )
146231 goto err_nsim_bus_dev_id_free ;
@@ -185,6 +270,14 @@ int nsim_bus_init(void)
185270
186271void nsim_bus_exit (void )
187272{
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 );
188281 driver_unregister (& nsim_driver );
189282 bus_unregister (& nsim_bus );
190283}
0 commit comments