@@ -3319,11 +3319,8 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
return -EINVAL;
/* Check that the size of the response buffer provided by the user is
- * large enough for the response's legacy fields and header.
- * Since this is the first version of this verb, this includes the
- * entire response struct. When adding extra fields to the response
- * struct, change this line as needed. */
- resp.response_length = sizeof(resp);
+ * large enough for the response's legacy fields and header. */
+ resp.response_length = offsetof(typeof(resp), odp_caps);
if (ucore->outlen < resp.response_length)
return -ENOSPC;
@@ -3334,6 +3331,24 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
copy_query_dev_fields(file, &resp.base, &attr);
resp.comp_mask = 0;
+ if (ucore->outlen < resp.response_length + sizeof(resp.odp_caps))
+ goto end;
+
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
+ resp.odp_caps.general_caps = attr.odp_caps.general_caps;
+ resp.odp_caps.per_transport_caps.rc_odp_caps =
+ attr.odp_caps.per_transport_caps.rc_odp_caps;
+ resp.odp_caps.per_transport_caps.uc_odp_caps =
+ attr.odp_caps.per_transport_caps.uc_odp_caps;
+ resp.odp_caps.per_transport_caps.ud_odp_caps =
+ attr.odp_caps.per_transport_caps.ud_odp_caps;
+ resp.odp_caps.reserved = 0;
+#else
+ memset(&resp.odp_caps, 0, sizeof(resp.odp_caps));
+#endif
+ resp.response_length += sizeof(resp.odp_caps);
+
+end:
err = ib_copy_to_udata(ucore, &resp, resp.response_length);
if (err)
return err;
@@ -207,10 +207,21 @@ struct ib_uverbs_ex_query_device {
__u32 reserved;
};
+struct ib_uverbs_odp_caps {
+ __u64 general_caps;
+ struct {
+ __u32 rc_odp_caps;
+ __u32 uc_odp_caps;
+ __u32 ud_odp_caps;
+ } per_transport_caps;
+ __u32 reserved;
+};
+
struct ib_uverbs_ex_query_device_resp {
struct ib_uverbs_query_device_resp base;
__u32 comp_mask;
__u32 response_length;
+ struct ib_uverbs_odp_caps odp_caps;
};
struct ib_uverbs_query_port {