-static int create_dp(int dp_idx, const char __user *devnamep)
-{
- struct odp_port internal_dev_port;
- char devname[IFNAMSIZ];
- struct datapath *dp;
- int err;
- int i;
-
- if (devnamep) {
- int retval = strncpy_from_user(devname, devnamep, IFNAMSIZ);
- if (retval < 0) {
- err = -EFAULT;
- goto err;
- } else if (retval >= IFNAMSIZ) {
- err = -ENAMETOOLONG;
- goto err;
- }
- } else {
- snprintf(devname, sizeof devname, "of%d", dp_idx);
- }
-
- rtnl_lock();
- mutex_lock(&dp_mutex);
- err = -ENODEV;
- if (!try_module_get(THIS_MODULE))
- goto err_unlock;
-
- /* Exit early if a datapath with that number already exists.
- * (We don't use -EEXIST because that's ambiguous with 'devname'
- * conflicting with an existing network device name.) */
- err = -EBUSY;
- if (get_dp(dp_idx))
- goto err_put_module;
-
- err = -ENOMEM;
- dp = kzalloc(sizeof *dp, GFP_KERNEL);
- if (dp == NULL)
- goto err_put_module;
- INIT_LIST_HEAD(&dp->port_list);
- mutex_init(&dp->mutex);
- dp->dp_idx = dp_idx;
- for (i = 0; i < DP_N_QUEUES; i++)
- skb_queue_head_init(&dp->queues[i]);
- init_waitqueue_head(&dp->waitqueue);
-
- /* Initialize kobject for bridge. This will be added as
- * /sys/class/net/<devname>/brif later, if sysfs is enabled. */
- dp->ifobj.kset = NULL;
- kobject_init(&dp->ifobj, &dp_ktype);
-
- /* Allocate table. */
- err = -ENOMEM;
- rcu_assign_pointer(dp->table, tbl_create(0));
- if (!dp->table)
- goto err_free_dp;
-
- /* Set up our datapath device. */
- BUILD_BUG_ON(sizeof(internal_dev_port.devname) != sizeof(devname));
- strcpy(internal_dev_port.devname, devname);
- strcpy(internal_dev_port.type, "internal");
- err = new_vport(dp, &internal_dev_port, ODPP_LOCAL);
- if (err) {
- if (err == -EBUSY)
- err = -EEXIST;
-
- goto err_destroy_table;
- }
-
- dp->drop_frags = 0;
- dp->stats_percpu = alloc_percpu(struct dp_stats_percpu);
- if (!dp->stats_percpu)
- goto err_destroy_local_port;
-
- rcu_assign_pointer(dps[dp_idx], dp);
- mutex_unlock(&dp_mutex);
- rtnl_unlock();
-
- dp_sysfs_add_dp(dp);
-
- return 0;
-
-err_destroy_local_port:
- dp_detach_port(dp->ports[ODPP_LOCAL]);
-err_destroy_table:
- tbl_destroy(dp->table, NULL);
-err_free_dp:
- kfree(dp);
-err_put_module:
- module_put(THIS_MODULE);
-err_unlock:
- mutex_unlock(&dp_mutex);
- rtnl_unlock();
-err:
- return err;
-}
-
-static void do_destroy_dp(struct datapath *dp)