diff options
-rw-r--r-- | drivers/infiniband/core/mad.c | 74 | ||||
-rw-r--r-- | drivers/infiniband/core/user_mad.c | 34 | ||||
-rw-r--r-- | include/rdma/ib_mad.h | 11 | ||||
-rw-r--r-- | include/uapi/rdma/ib_user_mad.h | 5 |
4 files changed, 88 insertions, 36 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 988bbda67952..74c30f4c557e 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
@@ -283,6 +283,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, | |||
283 | goto error1; | 283 | goto error1; |
284 | } | 284 | } |
285 | } | 285 | } |
286 | |||
286 | /* Make sure class supplied is consistent with QP type */ | 287 | /* Make sure class supplied is consistent with QP type */ |
287 | if (qp_type == IB_QPT_SMI) { | 288 | if (qp_type == IB_QPT_SMI) { |
288 | if ((mad_reg_req->mgmt_class != | 289 | if ((mad_reg_req->mgmt_class != |
@@ -309,6 +310,8 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, | |||
309 | /* No registration request supplied */ | 310 | /* No registration request supplied */ |
310 | if (!send_handler) | 311 | if (!send_handler) |
311 | goto error1; | 312 | goto error1; |
313 | if (registration_flags & IB_MAD_USER_RMPP) | ||
314 | goto error1; | ||
312 | } | 315 | } |
313 | 316 | ||
314 | /* Validate device and port */ | 317 | /* Validate device and port */ |
@@ -907,6 +910,12 @@ static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr, | |||
907 | return 0; | 910 | return 0; |
908 | } | 911 | } |
909 | 912 | ||
913 | int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent) | ||
914 | { | ||
915 | return agent->rmpp_version && !(agent->flags & IB_MAD_USER_RMPP); | ||
916 | } | ||
917 | EXPORT_SYMBOL(ib_mad_kernel_rmpp_agent); | ||
918 | |||
910 | struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, | 919 | struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, |
911 | u32 remote_qpn, u16 pkey_index, | 920 | u32 remote_qpn, u16 pkey_index, |
912 | int rmpp_active, | 921 | int rmpp_active, |
@@ -923,10 +932,12 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, | |||
923 | pad = get_pad_size(hdr_len, data_len); | 932 | pad = get_pad_size(hdr_len, data_len); |
924 | message_size = hdr_len + data_len + pad; | 933 | message_size = hdr_len + data_len + pad; |
925 | 934 | ||
926 | if ((!mad_agent->rmpp_version && | 935 | if (ib_mad_kernel_rmpp_agent(mad_agent)) { |
927 | (rmpp_active || message_size > sizeof(struct ib_mad))) || | 936 | if (!rmpp_active && message_size > sizeof(struct ib_mad)) |
928 | (!rmpp_active && message_size > sizeof(struct ib_mad))) | 937 | return ERR_PTR(-EINVAL); |
929 | return ERR_PTR(-EINVAL); | 938 | } else |
939 | if (rmpp_active || message_size > sizeof(struct ib_mad)) | ||
940 | return ERR_PTR(-EINVAL); | ||
930 | 941 | ||
931 | size = rmpp_active ? hdr_len : sizeof(struct ib_mad); | 942 | size = rmpp_active ? hdr_len : sizeof(struct ib_mad); |
932 | buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); | 943 | buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); |
@@ -1180,7 +1191,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf, | |||
1180 | &mad_agent_priv->send_list); | 1191 | &mad_agent_priv->send_list); |
1181 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 1192 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |
1182 | 1193 | ||
1183 | if (mad_agent_priv->agent.rmpp_version) { | 1194 | if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { |
1184 | ret = ib_send_rmpp_mad(mad_send_wr); | 1195 | ret = ib_send_rmpp_mad(mad_send_wr); |
1185 | if (ret >= 0 && ret != IB_RMPP_RESULT_CONSUMED) | 1196 | if (ret >= 0 && ret != IB_RMPP_RESULT_CONSUMED) |
1186 | ret = ib_send_mad(mad_send_wr); | 1197 | ret = ib_send_mad(mad_send_wr); |
@@ -1730,6 +1741,7 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, | |||
1730 | 1741 | ||
1731 | rmpp_mad = (struct ib_rmpp_mad *)mad_hdr; | 1742 | rmpp_mad = (struct ib_rmpp_mad *)mad_hdr; |
1732 | return !mad_agent_priv->agent.rmpp_version || | 1743 | return !mad_agent_priv->agent.rmpp_version || |
1744 | !ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent) || | ||
1733 | !(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & | 1745 | !(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & |
1734 | IB_MGMT_RMPP_FLAG_ACTIVE) || | 1746 | IB_MGMT_RMPP_FLAG_ACTIVE) || |
1735 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); | 1747 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); |
@@ -1857,7 +1869,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
1857 | 1869 | ||
1858 | INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); | 1870 | INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); |
1859 | list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); | 1871 | list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); |
1860 | if (mad_agent_priv->agent.rmpp_version) { | 1872 | if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { |
1861 | mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, | 1873 | mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, |
1862 | mad_recv_wc); | 1874 | mad_recv_wc); |
1863 | if (!mad_recv_wc) { | 1875 | if (!mad_recv_wc) { |
@@ -1872,23 +1884,39 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
1872 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); | 1884 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); |
1873 | if (!mad_send_wr) { | 1885 | if (!mad_send_wr) { |
1874 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 1886 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |
1875 | ib_free_recv_mad(mad_recv_wc); | 1887 | if (!ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent) |
1876 | deref_mad_agent(mad_agent_priv); | 1888 | && ib_is_mad_class_rmpp(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class) |
1877 | return; | 1889 | && (ib_get_rmpp_flags(&((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr) |
1878 | } | 1890 | & IB_MGMT_RMPP_FLAG_ACTIVE)) { |
1879 | ib_mark_mad_done(mad_send_wr); | 1891 | /* user rmpp is in effect |
1880 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 1892 | * and this is an active RMPP MAD |
1893 | */ | ||
1894 | mad_recv_wc->wc->wr_id = 0; | ||
1895 | mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, | ||
1896 | mad_recv_wc); | ||
1897 | atomic_dec(&mad_agent_priv->refcount); | ||
1898 | } else { | ||
1899 | /* not user rmpp, revert to normal behavior and | ||
1900 | * drop the mad */ | ||
1901 | ib_free_recv_mad(mad_recv_wc); | ||
1902 | deref_mad_agent(mad_agent_priv); | ||
1903 | return; | ||
1904 | } | ||
1905 | } else { | ||
1906 | ib_mark_mad_done(mad_send_wr); | ||
1907 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | ||
1881 | 1908 | ||
1882 | /* Defined behavior is to complete response before request */ | 1909 | /* Defined behavior is to complete response before request */ |
1883 | mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf; | 1910 | mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf; |
1884 | mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, | 1911 | mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, |
1885 | mad_recv_wc); | 1912 | mad_recv_wc); |
1886 | atomic_dec(&mad_agent_priv->refcount); | 1913 | atomic_dec(&mad_agent_priv->refcount); |
1887 | 1914 | ||
1888 | mad_send_wc.status = IB_WC_SUCCESS; | 1915 | mad_send_wc.status = IB_WC_SUCCESS; |
1889 | mad_send_wc.vendor_err = 0; | 1916 | mad_send_wc.vendor_err = 0; |
1890 | mad_send_wc.send_buf = &mad_send_wr->send_buf; | 1917 | mad_send_wc.send_buf = &mad_send_wr->send_buf; |
1891 | ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc); | 1918 | ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc); |
1919 | } | ||
1892 | } else { | 1920 | } else { |
1893 | mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, | 1921 | mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, |
1894 | mad_recv_wc); | 1922 | mad_recv_wc); |
@@ -2128,7 +2156,7 @@ void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, | |||
2128 | 2156 | ||
2129 | mad_agent_priv = mad_send_wr->mad_agent_priv; | 2157 | mad_agent_priv = mad_send_wr->mad_agent_priv; |
2130 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 2158 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
2131 | if (mad_agent_priv->agent.rmpp_version) { | 2159 | if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { |
2132 | ret = ib_process_rmpp_send_wc(mad_send_wr, mad_send_wc); | 2160 | ret = ib_process_rmpp_send_wc(mad_send_wr, mad_send_wc); |
2133 | if (ret == IB_RMPP_RESULT_CONSUMED) | 2161 | if (ret == IB_RMPP_RESULT_CONSUMED) |
2134 | goto done; | 2162 | goto done; |
@@ -2524,7 +2552,7 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr) | |||
2524 | 2552 | ||
2525 | mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms); | 2553 | mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms); |
2526 | 2554 | ||
2527 | if (mad_send_wr->mad_agent_priv->agent.rmpp_version) { | 2555 | if (ib_mad_kernel_rmpp_agent(&mad_send_wr->mad_agent_priv->agent)) { |
2528 | ret = ib_retry_rmpp(mad_send_wr); | 2556 | ret = ib_retry_rmpp(mad_send_wr); |
2529 | switch (ret) { | 2557 | switch (ret) { |
2530 | case IB_RMPP_RESULT_UNHANDLED: | 2558 | case IB_RMPP_RESULT_UNHANDLED: |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 11af1c61c135..928cdd20e2d1 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -506,13 +506,15 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
506 | 506 | ||
507 | rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; | 507 | rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; |
508 | hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); | 508 | hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); |
509 | if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) { | 509 | |
510 | copy_offset = IB_MGMT_MAD_HDR; | 510 | if (ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class) |
511 | rmpp_active = 0; | 511 | && ib_mad_kernel_rmpp_agent(agent)) { |
512 | } else { | ||
513 | copy_offset = IB_MGMT_RMPP_HDR; | 512 | copy_offset = IB_MGMT_RMPP_HDR; |
514 | rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & | 513 | rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & |
515 | IB_MGMT_RMPP_FLAG_ACTIVE; | 514 | IB_MGMT_RMPP_FLAG_ACTIVE; |
515 | } else { | ||
516 | copy_offset = IB_MGMT_MAD_HDR; | ||
517 | rmpp_active = 0; | ||
516 | } | 518 | } |
517 | 519 | ||
518 | data_len = count - hdr_size(file) - hdr_len; | 520 | data_len = count - hdr_size(file) - hdr_len; |
@@ -558,14 +560,22 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
558 | rmpp_mad->mad_hdr.tid = *tid; | 560 | rmpp_mad->mad_hdr.tid = *tid; |
559 | } | 561 | } |
560 | 562 | ||
561 | spin_lock_irq(&file->send_lock); | 563 | if (!ib_mad_kernel_rmpp_agent(agent) |
562 | ret = is_duplicate(file, packet); | 564 | && ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class) |
563 | if (!ret) | 565 | && (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) { |
566 | spin_lock_irq(&file->send_lock); | ||
564 | list_add_tail(&packet->list, &file->send_list); | 567 | list_add_tail(&packet->list, &file->send_list); |
565 | spin_unlock_irq(&file->send_lock); | 568 | spin_unlock_irq(&file->send_lock); |
566 | if (ret) { | 569 | } else { |
567 | ret = -EINVAL; | 570 | spin_lock_irq(&file->send_lock); |
568 | goto err_msg; | 571 | ret = is_duplicate(file, packet); |
572 | if (!ret) | ||
573 | list_add_tail(&packet->list, &file->send_list); | ||
574 | spin_unlock_irq(&file->send_lock); | ||
575 | if (ret) { | ||
576 | ret = -EINVAL; | ||
577 | goto err_msg; | ||
578 | } | ||
569 | } | 579 | } |
570 | 580 | ||
571 | ret = ib_post_send_mad(packet->msg, NULL); | 581 | ret = ib_post_send_mad(packet->msg, NULL); |
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 876f497f8b0c..9bb99e983f58 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/list.h> | 40 | #include <linux/list.h> |
41 | 41 | ||
42 | #include <rdma/ib_verbs.h> | 42 | #include <rdma/ib_verbs.h> |
43 | #include <uapi/rdma/ib_user_mad.h> | ||
43 | 44 | ||
44 | /* Management base version */ | 45 | /* Management base version */ |
45 | #define IB_MGMT_BASE_VERSION 1 | 46 | #define IB_MGMT_BASE_VERSION 1 |
@@ -359,6 +360,9 @@ typedef void (*ib_mad_recv_handler)(struct ib_mad_agent *mad_agent, | |||
359 | * @port_num: Port number on which QP is registered | 360 | * @port_num: Port number on which QP is registered |
360 | * @rmpp_version: If set, indicates the RMPP version used by this agent. | 361 | * @rmpp_version: If set, indicates the RMPP version used by this agent. |
361 | */ | 362 | */ |
363 | enum { | ||
364 | IB_MAD_USER_RMPP = IB_USER_MAD_USER_RMPP, | ||
365 | }; | ||
362 | struct ib_mad_agent { | 366 | struct ib_mad_agent { |
363 | struct ib_device *device; | 367 | struct ib_device *device; |
364 | struct ib_qp *qp; | 368 | struct ib_qp *qp; |
@@ -666,4 +670,11 @@ void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num); | |||
666 | */ | 670 | */ |
667 | void ib_free_send_mad(struct ib_mad_send_buf *send_buf); | 671 | void ib_free_send_mad(struct ib_mad_send_buf *send_buf); |
668 | 672 | ||
673 | /** | ||
674 | * ib_mad_kernel_rmpp_agent - Returns if the agent is performing RMPP. | ||
675 | * @agent: the agent in question | ||
676 | * @return: true if agent is performing rmpp, false otherwise. | ||
677 | */ | ||
678 | int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent); | ||
679 | |||
669 | #endif /* IB_MAD_H */ | 680 | #endif /* IB_MAD_H */ |
diff --git a/include/uapi/rdma/ib_user_mad.h b/include/uapi/rdma/ib_user_mad.h index c00b081dc10e..09f809f323ea 100644 --- a/include/uapi/rdma/ib_user_mad.h +++ b/include/uapi/rdma/ib_user_mad.h | |||
@@ -213,7 +213,10 @@ struct ib_user_mad_reg_req { | |||
213 | * used. | 213 | * used. |
214 | * @rmpp_version - If set, indicates the RMPP version to use. | 214 | * @rmpp_version - If set, indicates the RMPP version to use. |
215 | */ | 215 | */ |
216 | #define IB_USER_MAD_REG_FLAGS_CAP (0) | 216 | enum { |
217 | IB_USER_MAD_USER_RMPP = (1 << 0), | ||
218 | }; | ||
219 | #define IB_USER_MAD_REG_FLAGS_CAP (IB_USER_MAD_USER_RMPP) | ||
217 | struct ib_user_mad_reg_req2 { | 220 | struct ib_user_mad_reg_req2 { |
218 | __u32 id; | 221 | __u32 id; |
219 | __u32 qpn; | 222 | __u32 qpn; |