|
@@ -874,11 +874,11 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int get_pad_size(int hdr_len, int data_len)
|
|
|
+static int get_pad_size(int hdr_len, int data_len, size_t mad_size)
|
|
|
{
|
|
|
int seg_size, pad;
|
|
|
|
|
|
- seg_size = sizeof(struct ib_mad) - hdr_len;
|
|
|
+ seg_size = mad_size - hdr_len;
|
|
|
if (data_len && seg_size) {
|
|
|
pad = seg_size - data_len % seg_size;
|
|
|
return pad == seg_size ? 0 : pad;
|
|
@@ -897,14 +897,15 @@ static void free_send_rmpp_list(struct ib_mad_send_wr_private *mad_send_wr)
|
|
|
}
|
|
|
|
|
|
static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr,
|
|
|
- gfp_t gfp_mask)
|
|
|
+ size_t mad_size, gfp_t gfp_mask)
|
|
|
{
|
|
|
struct ib_mad_send_buf *send_buf = &send_wr->send_buf;
|
|
|
struct ib_rmpp_mad *rmpp_mad = send_buf->mad;
|
|
|
struct ib_rmpp_segment *seg = NULL;
|
|
|
int left, seg_size, pad;
|
|
|
|
|
|
- send_buf->seg_size = sizeof(struct ib_mad) - send_buf->hdr_len;
|
|
|
+ send_buf->seg_size = mad_size - send_buf->hdr_len;
|
|
|
+ send_buf->seg_rmpp_size = mad_size - IB_MGMT_RMPP_HDR;
|
|
|
seg_size = send_buf->seg_size;
|
|
|
pad = send_wr->pad;
|
|
|
|
|
@@ -954,20 +955,30 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
|
|
|
struct ib_mad_send_wr_private *mad_send_wr;
|
|
|
int pad, message_size, ret, size;
|
|
|
void *buf;
|
|
|
+ size_t mad_size;
|
|
|
+ bool opa;
|
|
|
|
|
|
mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
|
|
|
agent);
|
|
|
- pad = get_pad_size(hdr_len, data_len);
|
|
|
+
|
|
|
+ opa = rdma_cap_opa_mad(mad_agent->device, mad_agent->port_num);
|
|
|
+
|
|
|
+ if (opa && base_version == OPA_MGMT_BASE_VERSION)
|
|
|
+ mad_size = sizeof(struct opa_mad);
|
|
|
+ else
|
|
|
+ mad_size = sizeof(struct ib_mad);
|
|
|
+
|
|
|
+ pad = get_pad_size(hdr_len, data_len, mad_size);
|
|
|
message_size = hdr_len + data_len + pad;
|
|
|
|
|
|
if (ib_mad_kernel_rmpp_agent(mad_agent)) {
|
|
|
- if (!rmpp_active && message_size > sizeof(struct ib_mad))
|
|
|
+ if (!rmpp_active && message_size > mad_size)
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
} else
|
|
|
- if (rmpp_active || message_size > sizeof(struct ib_mad))
|
|
|
+ if (rmpp_active || message_size > mad_size)
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
|
- size = rmpp_active ? hdr_len : sizeof(struct ib_mad);
|
|
|
+ size = rmpp_active ? hdr_len : mad_size;
|
|
|
buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask);
|
|
|
if (!buf)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
@@ -982,7 +993,14 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
|
|
|
mad_send_wr->mad_agent_priv = mad_agent_priv;
|
|
|
mad_send_wr->sg_list[0].length = hdr_len;
|
|
|
mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey;
|
|
|
- mad_send_wr->sg_list[1].length = sizeof(struct ib_mad) - hdr_len;
|
|
|
+
|
|
|
+ /* OPA MADs don't have to be the full 2048 bytes */
|
|
|
+ if (opa && base_version == OPA_MGMT_BASE_VERSION &&
|
|
|
+ data_len < mad_size - hdr_len)
|
|
|
+ mad_send_wr->sg_list[1].length = data_len;
|
|
|
+ else
|
|
|
+ mad_send_wr->sg_list[1].length = mad_size - hdr_len;
|
|
|
+
|
|
|
mad_send_wr->sg_list[1].lkey = mad_agent->mr->lkey;
|
|
|
|
|
|
mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;
|
|
@@ -995,7 +1013,7 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
|
|
|
mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;
|
|
|
|
|
|
if (rmpp_active) {
|
|
|
- ret = alloc_send_rmpp_list(mad_send_wr, gfp_mask);
|
|
|
+ ret = alloc_send_rmpp_list(mad_send_wr, mad_size, gfp_mask);
|
|
|
if (ret) {
|
|
|
kfree(buf);
|
|
|
return ERR_PTR(ret);
|
|
@@ -2976,6 +2994,10 @@ static int ib_mad_port_open(struct ib_device *device,
|
|
|
if (WARN_ON(rdma_max_mad_size(device, port_num) < IB_MGMT_MAD_SIZE))
|
|
|
return -EFAULT;
|
|
|
|
|
|
+ if (WARN_ON(rdma_cap_opa_mad(device, port_num) &&
|
|
|
+ rdma_max_mad_size(device, port_num) < OPA_MGMT_MAD_SIZE))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
/* Create new device info */
|
|
|
port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
|
|
|
if (!port_priv) {
|