aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/mad.c74
-rw-r--r--drivers/infiniband/core/user_mad.c34
-rw-r--r--include/rdma/ib_mad.h11
-rw-r--r--include/uapi/rdma/ib_user_mad.h5
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
913int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent)
914{
915 return agent->rmpp_version && !(agent->flags & IB_MAD_USER_RMPP);
916}
917EXPORT_SYMBOL(ib_mad_kernel_rmpp_agent);
918
910struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, 919struct 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 */
363enum {
364 IB_MAD_USER_RMPP = IB_USER_MAD_USER_RMPP,
365};
362struct ib_mad_agent { 366struct 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 */
667void ib_free_send_mad(struct ib_mad_send_buf *send_buf); 671void 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 */
678int 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) 216enum {
217 IB_USER_MAD_USER_RMPP = (1 << 0),
218};
219#define IB_USER_MAD_REG_FLAGS_CAP (IB_USER_MAD_USER_RMPP)
217struct ib_user_mad_reg_req2 { 220struct ib_user_mad_reg_req2 {
218 __u32 id; 221 __u32 id;
219 __u32 qpn; 222 __u32 qpn;