diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/infiniband/core/mad.c | 74 | ||||
| -rw-r--r-- | drivers/infiniband/core/user_mad.c | 34 |
2 files changed, 73 insertions, 35 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); |
