@@ -44,3 +44,8 @@ config MLX4_DEBUG
mlx4_core driver. The output can be turned on via the
debug_level module parameter (which can also be set after
the driver is loaded through sysfs).
+
+config MLX4_DEV_C
+ tristate "mlx4 driver pre-loading configuration module"
+ depends on DEVCONF
+ default m
@@ -8,3 +8,7 @@ obj-$(CONFIG_MLX4_EN) += mlx4_en.o
mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
en_resources.o en_netdev.o en_selftest.o en_clock.o
mlx4_en-$(CONFIG_MLX4_EN_DCB) += en_dcb_nl.o
+
+obj-$(CONFIG_MLX4_DEV_C) += dev_c_mlx4.o
+
+dev_c_mlx4-y := mlx4_conf.o
new file mode 100644
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/configfs.h>
+#include <linux/devconf.h>
+#include <linux/mlx4/device.h>
+
+struct mlx4_port {
+ struct devconf_config_object cobj;
+ int type;
+};
+
+struct mlx4_bdf_config {
+ struct devconf_config_object cobj;
+ int dmfs;
+};
+
+static inline struct mlx4_bdf_config *to_bdf_config(struct config_item *item)
+{
+ struct devconf_config_object *cobj = to_config_obj(item);
+
+ return cobj ? container_of(cobj, struct mlx4_bdf_config, cobj) : NULL;
+}
+
+static inline struct mlx4_port *to_simple_port(struct config_item *item)
+{
+ struct devconf_config_object *cobj = to_config_obj(item);
+
+ return cobj ? container_of(cobj, struct mlx4_port, cobj) : NULL;
+}
+
+static inline struct mlx4_bdf_config
+*cobj_to_bdf_config(struct devconf_config_object *cobj)
+{
+ return cobj ? container_of(cobj, struct mlx4_bdf_config, cobj) : NULL;
+}
+
+static inline struct mlx4_port
+*cobj_to_port(struct devconf_config_object *cobj)
+{
+ return cobj ? container_of(cobj, struct mlx4_port, cobj) : NULL;
+}
+
+static struct configfs_attribute simple_port_attr_type = {
+ .ca_owner = THIS_MODULE,
+ .ca_name = "type",
+ .ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute *simple_port_attrs[] = {
+ &simple_port_attr_type,
+ NULL,
+};
+
+static ssize_t config_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct mlx4_bdf_config *bdf_config;
+ struct mlx4_port *simple_port;
+ ssize_t count = -ENOENT;
+
+ if (strcmp(attr->ca_name, "dmfs")) {
+ bdf_config = to_bdf_config(item);
+ count = sprintf(page, "%d\n", bdf_config->dmfs);
+ } else if (strcmp(attr->ca_name, "type")) {
+ simple_port = to_simple_port(item);
+ count = sprintf(page, "%d\n", simple_port->type);
+ }
+ return count;
+}
+
+static ssize_t config_attr_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct mlx4_bdf_config *bdf_config;
+ struct mlx4_port *simple_port;
+ int err;
+ unsigned long res;
+
+ err = kstrtoul(page, 10, &res);
+ if (err)
+ return err;
+ if (strcmp(attr->ca_name, "dmfs")) {
+ bdf_config = to_bdf_config(item);
+ bdf_config->dmfs = res;
+ } else if (strcmp(attr->ca_name, "type")) {
+ simple_port = to_simple_port(item);
+ simple_port->type = res;
+ }
+
+ return count;
+}
+
+static void simple_port_release(struct config_item *item)
+{
+ kfree(to_simple_port(item));
+}
+
+static struct configfs_item_operations simple_port_item_ops = {
+ .release = simple_port_release,
+ .show_attribute = config_attr_show,
+ .store_attribute = config_attr_store,
+};
+
+static struct config_item_type simple_port_config_type = {
+ .ct_item_ops = &simple_port_item_ops,
+ .ct_attrs = simple_port_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item *simple_port_make_item(struct config_group *group,
+ const char *name)
+{
+ struct mlx4_port *simple_port;
+
+ simple_port = kzalloc(sizeof(*simple_port), GFP_KERNEL);
+ if (!simple_port)
+ return ERR_PTR(-ENOMEM);
+
+ config_item_init_type_name(&simple_port->cobj.group.cg_item, name,
+ &simple_port_config_type);
+
+ simple_port->type = 0;
+
+ return &simple_port->cobj.group.cg_item;
+}
+
+static struct configfs_group_operations ports_group_ops = {
+ .make_item = simple_port_make_item,
+};
+
+static void cobj_release(struct config_item *item)
+{
+ kfree(to_config_obj(item));
+}
+
+static struct configfs_item_operations ports_item_ops = {
+ .release = cobj_release,
+};
+
+static struct config_item_type ports_config_type = {
+ .ct_item_ops = &ports_item_ops,
+ .ct_group_ops = &ports_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *bdf_make_group(struct config_group *group,
+ const char *name)
+{
+ struct devconf_config_object *ports_config;
+
+ ports_config = kzalloc(sizeof(*ports_config), GFP_KERNEL);
+ if (!ports_config)
+ return ERR_PTR(-ENOMEM);
+
+ config_group_init_type_name(&ports_config->group, name,
+ &ports_config_type);
+
+ return &ports_config->group;
+}
+
+static struct configfs_group_operations bdf_group_ops = {
+ .make_group = bdf_make_group,
+};
+
+static void bdf_config_release(struct config_item *item)
+{
+ kfree(to_bdf_config(item));
+}
+
+static struct configfs_item_operations bdf_item_ops = {
+ .release = bdf_config_release,
+ .show_attribute = config_attr_show,
+ .store_attribute = config_attr_store,
+};
+
+static struct configfs_attribute config_attr_dmfs = {
+ .ca_owner = THIS_MODULE,
+ .ca_name = "dmfs",
+ .ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute *bdf_config_attrs[] = {
+ &config_attr_dmfs,
+ NULL,
+};
+
+static struct config_item_type bdf_config_type = {
+ .ct_item_ops = &bdf_item_ops,
+ .ct_group_ops = &bdf_group_ops,
+ .ct_attrs = bdf_config_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *pdevs_make_group(struct config_group *group,
+ const char *name)
+{
+ struct mlx4_bdf_config *bdf_config;
+
+ bdf_config = kzalloc(sizeof(*bdf_config), GFP_KERNEL);
+ if (!bdf_config)
+ return ERR_PTR(-ENOMEM);
+
+ config_group_init_type_name(&bdf_config->cobj.group, name,
+ &bdf_config_type);
+
+ return &bdf_config->cobj.group;
+}
+
+static struct configfs_group_operations pdevs_group_ops = {
+ .make_group = pdevs_make_group,
+};
+
+static struct configfs_item_operations pdevs_item_ops = {
+ .release = cobj_release,
+};
+
+static struct config_item_type pdevs_config_type = {
+ .ct_item_ops = &pdevs_item_ops,
+ .ct_group_ops = &pdevs_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *mlx4_make_group(struct config_group *group,
+ const char *name)
+{
+ struct devconf_config_object *pdevs_cobj;
+
+ pdevs_cobj = kzalloc(sizeof(*pdevs_cobj), GFP_KERNEL);
+ if (!pdevs_cobj)
+ return ERR_PTR(-ENOMEM);
+
+ config_group_init_type_name(&pdevs_cobj->group, name,
+ &pdevs_config_type);
+
+ return &pdevs_cobj->group;
+}
+
+static struct configfs_group_operations mlx4_group_ops = {
+ .make_group = mlx4_make_group,
+};
+
+static void mlx4_release(struct config_item *item)
+{
+ struct devconf_config_driver *cdrv = to_config_driver(item);
+
+ devconf_put_config_driver(cdrv);
+}
+
+static struct configfs_item_operations mlx4_item_ops = {
+ .release = mlx4_release,
+};
+
+static struct config_item_type mlx4_config_type = {
+ .ct_item_ops = &mlx4_item_ops,
+ .ct_group_ops = &mlx4_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static int mlx4_get_int_attr(struct devconf_config_object *cobj,
+ const char *attr_name, int *val)
+{
+ struct mlx4_port *simple_port;
+ struct mlx4_bdf_config *bdf_config;
+
+ if (strcmp(attr_name, "dmfs")) {
+ bdf_config = cobj_to_bdf_config(cobj);
+ *val = bdf_config->dmfs;
+ } else if (strcmp(attr_name, "type")) {
+ simple_port = cobj_to_port(cobj);
+ *val = simple_port->type;
+ } else {
+ return -ENOENT;
+ }
+ return 0;
+}
+
+static void mlx4_set_config_object(struct devconf_config_driver *cdrv,
+ const char *name)
+{
+ config_group_init_type_name(&cdrv->cobj.group, name, &mlx4_config_type);
+}
+
+DECLARE_DEVCONF_DRIVER_INIT(mlx4_core,
+ mlx4_set_config_object,
+ mlx4_get_int_attr);
+
+MODULE_LICENSE("GPL");