RDMA: Add indication for in kernel API support to IB device
authorGal Pressman <galpress@amazon.com>
Tue, 22 Jan 2019 08:08:22 +0000 (10:08 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 31 Jan 2019 03:32:25 +0000 (20:32 -0700)
Drivers that do not provide kernel verbs support should not be used by ib
kernel clients at all.

In case a device does not implement all mandatory verbs for kverbs usage
mark it as a non kverbs provider and prevent its usage for all clients
except for uverbs.

The device is marked as a non kverbs provider using the 'kverbs_provider'
flag which should only be set by the core code.  The clients can choose
whether kverbs are requested for its usage using the 'no_kverbs_req' flag
which is currently set for uverbs only.

This patch allows drivers to remove mandatory verbs stubs and simply set
the callbacks to NULL. The IB device will be registered as a non-kverbs
provider. Note that verbs that are required for the device registration
process must be implemented.

Signed-off-by: Gal Pressman <galpress@amazon.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/device.c
drivers/infiniband/core/uverbs_main.c
include/rdma/ib_verbs.h

index b511cfa00bdb6b2768cd0856a8466d4c19e9ad08..9d2e108235e94584c42d6338bc862f27e8feaa79 100644 (file)
@@ -121,13 +121,12 @@ static int ib_device_check_mandatory(struct ib_device *device)
        };
        int i;
 
+       device->kverbs_provider = true;
        for (i = 0; i < ARRAY_SIZE(mandatory_table); ++i) {
                if (!*(void **) ((void *) &device->ops +
                                 mandatory_table[i].offset)) {
-                       dev_warn(&device->dev,
-                                "Device is missing mandatory function %s\n",
-                                mandatory_table[i].name);
-                       return -EINVAL;
+                       device->kverbs_provider = false;
+                       break;
                }
        }
 
@@ -325,6 +324,9 @@ static int add_client_context(struct ib_device *device, struct ib_client *client
 {
        struct ib_client_data *context;
 
+       if (!device->kverbs_provider && !client->no_kverbs_req)
+               return -EOPNOTSUPP;
+
        context = kmalloc(sizeof(*context), GFP_KERNEL);
        if (!context)
                return -ENOMEM;
index 996f167d14360ab38fb2f97fceaefb7230478c9d..d628747e058c482569a30c3946a45169f61384c0 100644 (file)
@@ -1151,6 +1151,7 @@ static const struct file_operations uverbs_mmap_fops = {
 
 static struct ib_client uverbs_client = {
        .name   = "uverbs",
+       .no_kverbs_req = true,
        .add    = ib_uverbs_add_one,
        .remove = ib_uverbs_remove_one
 };
index a1a1e710642cbf528235461bccc800951145ad35..4183a03b46b5caabaa461893a6714ec989089b43 100644 (file)
@@ -2565,6 +2565,8 @@ struct ib_device {
        __be64                       node_guid;
        u32                          local_dma_lkey;
        u16                          is_switch:1;
+       /* Indicates kernel verbs support, should not be used in drivers */
+       u16                          kverbs_provider:1;
        u8                           node_type;
        u8                           phys_port_cnt;
        struct ib_device_attr        attrs;
@@ -2619,6 +2621,9 @@ struct ib_client {
                        const struct sockaddr *addr,
                        void *client_data);
        struct list_head list;
+
+       /* kverbs are not required by the client */
+       u8 no_kverbs_req:1;
 };
 
 struct ib_device *_ib_alloc_device(size_t size);