}
return err;
}
+
+static clib_error_t *
+vnet_dev_config_driver_args (vlib_main_t *vm, unformat_input_t *input,
+ char *driver_name)
+{
+ vnet_dev_main_t *dm = &vnet_dev_main;
+ clib_error_t *err = 0;
+ u8 *args;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "args %U", unformat_single_quoted_string, &args))
+ ;
+ else
+ {
+ err = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, input);
+ break;
+ }
+ }
+
+ if (err == 0)
+ {
+ vnet_dev_driver_t *driver;
+ vnet_dev_rv_t rv = VNET_DEV_OK;
+
+ vec_foreach (driver, dm->drivers)
+ {
+ if (driver_name[0] &&
+ strcmp (driver_name, driver->registration->name))
+ continue;
+ if (driver->registration->drv_args)
+ {
+ for (vnet_dev_arg_t *a = driver->registration->drv_args;
+ a->type != VNET_DEV_ARG_END; a++)
+ vec_add1 (driver->args, *a);
+
+ if (args)
+ {
+ rv = vnet_dev_arg_parse (vm, NULL, driver->args, args);
+ if (rv != VNET_DEV_OK)
+ goto done;
+
+ if (driver->ops.config_args)
+ rv = driver->ops.config_args (vm, driver);
+ break;
+ }
+ }
+ }
+ done:
+ vec_free (args);
+
+ if (rv != VNET_DEV_OK)
+ err = clib_error_return (0, "error: %U for driver '%s'",
+ format_vnet_dev_rv, rv, driver_name);
+ }
+
+ return err;
+}
+
static clib_error_t *
vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input,
char *device_id)
vlib_frame_t *f)
{
vnet_dev_main_t *dm = &vnet_dev_main;
+ vnet_dev_driver_name_t driver_name;
unformat_input_t input;
clib_error_t *err = 0;
err = vnet_dev_config_one_device (vm, &no_input, device_id);
unformat_free (&no_input);
}
+ else if (unformat (&input, "driver %U %U", unformat_c_string_array,
+ driver_name, sizeof (driver_name),
+ unformat_vlib_cli_sub_input, &sub_input))
+ {
+ err = vnet_dev_config_driver_args (vm, &sub_input, driver_name);
+ unformat_free (&sub_input);
+ }
else
err = clib_error_return (0, "unknown input '%U'",
format_unformat_error, &input);
typedef struct vnet_dev_bus_registration vnet_dev_bus_registration_t;
typedef struct vnet_dev_driver_registration vnet_dev_driver_registration_t;
+typedef struct vnet_dev_driver vnet_dev_driver_t;
typedef struct vnet_dev vnet_dev_t;
typedef struct vnet_dev_port vnet_dev_port_t;
typedef struct vnet_dev_rx_queue vnet_dev_rx_queue_t;
typedef struct vnet_dev_counter_main vnet_dev_counter_main_t;
typedef struct vnet_dev_port_cfg_change_req vnet_dev_port_cfg_change_req_t;
+typedef vnet_dev_rv_t (vnet_dev_drv_op_t) (vlib_main_t *, vnet_dev_driver_t *);
typedef vnet_dev_rv_t (vnet_dev_op_t) (vlib_main_t *, vnet_dev_t *);
typedef vnet_dev_rv_t (vnet_dev_port_op_t) (vlib_main_t *, vnet_dev_port_t *);
typedef vnet_dev_rv_t (vnet_dev_port_cfg_change_op_t) (
typedef struct
{
+ vnet_dev_drv_op_t *config_args;
vnet_dev_op_t *alloc;
vnet_dev_op_t *init;
vnet_dev_op_no_rv_t *deinit;
int priority;
vnet_dev_ops_t ops;
vnet_dev_arg_t *args;
+ vnet_dev_arg_t *drv_args;
};
typedef struct
vnet_dev_bus_ops_t ops;
} vnet_dev_bus_t;
-typedef struct
+typedef struct vnet_dev_driver
{
u32 index;
void *dev_data;
u32 dev_class_index;
vnet_dev_bus_index_t bus_index;
vnet_dev_ops_t ops;
+ vnet_dev_arg_t *args;
} vnet_dev_driver_t;
typedef struct