diff options
Diffstat (limited to 'drivers/infiniband/core/mad.c')
-rw-r--r-- | drivers/infiniband/core/mad.c | 74 |
1 files changed, 51 insertions, 23 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: |