int abi_version);
void ibv_register_driver(const char *name, ibv_driver_init_func init_func);
+void ibv_register_driver_ext(const char *name, ibv_driver_init_func init_func);
int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd,
size_t cmd_size, struct ibv_get_context_resp *resp,
size_t resp_size);
BEGIN_C_DECLS
+enum ibv_extension_type {
+ IBV_EXTENSION_COMMON,
+ IBV_EXTENSION_VENDOR,
+ IBV_EXTENSION_OFA,
+ IBV_EXTENSION_RDMA_CM
+};
+#define IBV_EXTENSION_BASE_SHIFT 24
+#define IBV_EXTENSION_MASK 0xFF000000
+
union ibv_gid {
uint8_t raw[16];
struct {
IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11,
IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12,
IBV_DEVICE_SRQ_RESIZE = 1 << 13,
- IBV_DEVICE_N_NOTIFY_CQ = 1 << 14
+ IBV_DEVICE_N_NOTIFY_CQ = 1 << 14,
+ IBV_DEVICE_EXTENSIONS = 1 << (IBV_EXTENSION_BASE_SHIFT - 1)
};
enum ibv_atomic_cap {
char dev_path[IBV_SYSFS_PATH_MAX];
/* Path to infiniband class device in sysfs */
char ibdev_path[IBV_SYSFS_PATH_MAX];
+
+ /* Following fields only available if device supports extensions */
+ void *private;
+ int (*have_ext_ops)(struct ibv_device *device,
+ const char *ext_name);
+ void * (*get_device_ext_ops)(struct ibv_device *device,
+ const char *ext_name);
};
struct ibv_context_ops {
int num_comp_vectors;
pthread_mutex_t mutex;
void *abi_compat;
+
+ /* Following fields only available if device supports extensions */
+ void *private;
+ void * (*get_ext_ops)(struct ibv_context *context,
+ const char *ext_name);
};
/**
*/
uint64_t ibv_get_device_guid(struct ibv_device *device);
+/**
+ * ibv_have_ext_ops - Return true if device supports the requested
+ * extended operations.
+ */
+int ibv_have_ext_ops(struct ibv_device *device, const char *name);
+
+/**
+ * ibv_get_device_ext_ops - Return extended operations.
+ */
+void *ibv_get_device_ext_ops(struct ibv_device *device, const char *name);
+
/**
* ibv_open_device - Initialize device for use
*/
*/
int ibv_close_device(struct ibv_context *context);
+/**
+ * ibv_get_ext_ops - Return extended operations.
+ */
+void *ibv_get_ext_ops(struct ibv_context *context, const char *name);
+
/**
* ibv_get_async_event - Get next async event
* @event: Pointer to use to return async event
}
default_symver(__ibv_close_device, ibv_close_device);
+int __ibv_have_ext_ops(struct ibv_device *device, const char *name)
+{
+ if (!ibv_get_ext_support(device))
+ return ENOSYS;
+
+ return device->have_ext_ops(device, name);
+}
+default_symver(__ibv_have_ext_ops, ibv_have_ext_ops);
+
+void *__ibv_get_device_ext_ops(struct ibv_device *device, const char *name)
+{
+ if (!ibv_get_ext_support(device) || !device->get_device_ext_ops)
+ return NULL;
+
+ return device->get_device_ext_ops(device, name);
+}
+default_symver(__ibv_get_device_ext_ops, ibv_get_device_ext_ops);
+
int __ibv_get_async_event(struct ibv_context *context,
struct ibv_async_event *event)
{
#define IB_VERBS_H
#include <pthread.h>
+#include <string.h>
#include <infiniband/driver.h>
(cmd)->response = (uintptr_t) (out); \
} while (0)
+/*
+ * Support for extended operations is recorded at the end of
+ * the name character array. This way we don't need to query
+ * for the device capabilities with every call.
+ */
+static inline int ibv_get_ext_support(struct ibv_device *device)
+{
+ return device->name[IBV_SYSFS_NAME_MAX - 1];
+}
+
+static inline void ibv_set_ext_support(struct ibv_device *device,
+ int ext_supported)
+{
+ if (strlen(device->name) < IBV_SYSFS_NAME_MAX - 1)
+ device->name[IBV_SYSFS_NAME_MAX - 1] = (char) ext_supported;
+}
+
#endif /* IB_VERBS_H */
const char *name;
ibv_driver_init_func init_func;
struct ibv_driver *next;
+ int ext_support;
};
static struct ibv_sysfs_dev *sysfs_dev_list;
return ret;
}
-void ibv_register_driver(const char *name, ibv_driver_init_func init_func)
+static void __ibv_register_driver(const char *name, ibv_driver_init_func init_func,
+ int ext_support)
{
struct ibv_driver *driver;
driver->name = name;
driver->init_func = init_func;
driver->next = NULL;
+ driver->ext_support = ext_support;
if (tail_driver)
tail_driver->next = driver;
tail_driver = driver;
}
+void ibv_register_driver(const char *name, ibv_driver_init_func init_func)
+{
+ __ibv_register_driver(name, init_func, 0);
+}
+
+void ibv_register_driver_ext(const char *name, ibv_driver_init_func init_func)
+{
+ __ibv_register_driver(name, init_func, 1);
+}
+
static void load_driver(const char *name)
{
char *so_name;
strcpy(dev->name, sysfs_dev->ibdev_name);
strcpy(dev->ibdev_path, sysfs_dev->ibdev_path);
+ ibv_set_ext_support(dev, driver->ext_support);
+
return dev;
}
ibv_port_state_str;
ibv_event_type_str;
ibv_wc_status_str;
+
+ ibv_register_driver_ext;
+ ibv_have_ext_ops;
+ ibv_get_device_ext_ops;
+ ibv_get_ext_ops;
} IBVERBS_1.0;
}
}
+void *__ibv_get_ext_ops(struct ibv_context *context, const char *name)
+{
+ if (!ibv_get_ext_support(context->device) || !context->get_ext_ops)
+ return NULL;
+
+ return context->get_ext_ops(context, name);
+}
+default_symver(__ibv_get_ext_ops, ibv_get_ext_ops);
+
int __ibv_query_device(struct ibv_context *context,
struct ibv_device_attr *device_attr)
{