diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/agent.c | 19 | ||||
-rw-r--r-- | drivers/infiniband/core/mad.c | 50 | ||||
-rw-r--r-- | drivers/infiniband/core/smi.c | 16 | ||||
-rw-r--r-- | drivers/infiniband/core/smi.h | 2 |
4 files changed, 72 insertions, 15 deletions
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index ecd1a3057c61..db2633e4aae6 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved. | 3 | * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved. |
4 | * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. | 4 | * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. |
5 | * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. | 5 | * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. |
6 | * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved. | 6 | * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. |
7 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | 7 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. |
8 | * | 8 | * |
9 | * This software is available to you under a choice of one of two | 9 | * This software is available to you under a choice of one of two |
@@ -34,7 +34,6 @@ | |||
34 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 34 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
35 | * SOFTWARE. | 35 | * SOFTWARE. |
36 | * | 36 | * |
37 | * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $ | ||
38 | */ | 37 | */ |
39 | 38 | ||
40 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
@@ -42,6 +41,7 @@ | |||
42 | 41 | ||
43 | #include "agent.h" | 42 | #include "agent.h" |
44 | #include "smi.h" | 43 | #include "smi.h" |
44 | #include "mad_priv.h" | ||
45 | 45 | ||
46 | #define SPFX "ib_agent: " | 46 | #define SPFX "ib_agent: " |
47 | 47 | ||
@@ -87,8 +87,13 @@ int agent_send_response(struct ib_mad *mad, struct ib_grh *grh, | |||
87 | struct ib_mad_send_buf *send_buf; | 87 | struct ib_mad_send_buf *send_buf; |
88 | struct ib_ah *ah; | 88 | struct ib_ah *ah; |
89 | int ret; | 89 | int ret; |
90 | struct ib_mad_send_wr_private *mad_send_wr; | ||
91 | |||
92 | if (device->node_type == RDMA_NODE_IB_SWITCH) | ||
93 | port_priv = ib_get_agent_port(device, 0); | ||
94 | else | ||
95 | port_priv = ib_get_agent_port(device, port_num); | ||
90 | 96 | ||
91 | port_priv = ib_get_agent_port(device, port_num); | ||
92 | if (!port_priv) { | 97 | if (!port_priv) { |
93 | printk(KERN_ERR SPFX "Unable to find port agent\n"); | 98 | printk(KERN_ERR SPFX "Unable to find port agent\n"); |
94 | return -ENODEV; | 99 | return -ENODEV; |
@@ -113,6 +118,14 @@ int agent_send_response(struct ib_mad *mad, struct ib_grh *grh, | |||
113 | 118 | ||
114 | memcpy(send_buf->mad, mad, sizeof *mad); | 119 | memcpy(send_buf->mad, mad, sizeof *mad); |
115 | send_buf->ah = ah; | 120 | send_buf->ah = ah; |
121 | |||
122 | if (device->node_type == RDMA_NODE_IB_SWITCH) { | ||
123 | mad_send_wr = container_of(send_buf, | ||
124 | struct ib_mad_send_wr_private, | ||
125 | send_buf); | ||
126 | mad_send_wr->send_wr.wr.ud.port_num = port_num; | ||
127 | } | ||
128 | |||
116 | if ((ret = ib_post_send_mad(send_buf, NULL))) { | 129 | if ((ret = ib_post_send_mad(send_buf, NULL))) { |
117 | printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret); | 130 | printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret); |
118 | goto err2; | 131 | goto err2; |
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 85ccf13b8041..6b8faca02f8a 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
@@ -675,10 +675,16 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
675 | struct ib_mad_port_private *port_priv; | 675 | struct ib_mad_port_private *port_priv; |
676 | struct ib_mad_agent_private *recv_mad_agent = NULL; | 676 | struct ib_mad_agent_private *recv_mad_agent = NULL; |
677 | struct ib_device *device = mad_agent_priv->agent.device; | 677 | struct ib_device *device = mad_agent_priv->agent.device; |
678 | u8 port_num = mad_agent_priv->agent.port_num; | 678 | u8 port_num; |
679 | struct ib_wc mad_wc; | 679 | struct ib_wc mad_wc; |
680 | struct ib_send_wr *send_wr = &mad_send_wr->send_wr; | 680 | struct ib_send_wr *send_wr = &mad_send_wr->send_wr; |
681 | 681 | ||
682 | if (device->node_type == RDMA_NODE_IB_SWITCH && | ||
683 | smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) | ||
684 | port_num = send_wr->wr.ud.port_num; | ||
685 | else | ||
686 | port_num = mad_agent_priv->agent.port_num; | ||
687 | |||
682 | /* | 688 | /* |
683 | * Directed route handling starts if the initial LID routed part of | 689 | * Directed route handling starts if the initial LID routed part of |
684 | * a request or the ending LID routed part of a response is empty. | 690 | * a request or the ending LID routed part of a response is empty. |
@@ -1839,6 +1845,7 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, | |||
1839 | struct ib_mad_private *recv, *response; | 1845 | struct ib_mad_private *recv, *response; |
1840 | struct ib_mad_list_head *mad_list; | 1846 | struct ib_mad_list_head *mad_list; |
1841 | struct ib_mad_agent_private *mad_agent; | 1847 | struct ib_mad_agent_private *mad_agent; |
1848 | int port_num; | ||
1842 | 1849 | ||
1843 | response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL); | 1850 | response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL); |
1844 | if (!response) | 1851 | if (!response) |
@@ -1872,25 +1879,50 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, | |||
1872 | if (!validate_mad(&recv->mad.mad, qp_info->qp->qp_num)) | 1879 | if (!validate_mad(&recv->mad.mad, qp_info->qp->qp_num)) |
1873 | goto out; | 1880 | goto out; |
1874 | 1881 | ||
1882 | if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) | ||
1883 | port_num = wc->port_num; | ||
1884 | else | ||
1885 | port_num = port_priv->port_num; | ||
1886 | |||
1875 | if (recv->mad.mad.mad_hdr.mgmt_class == | 1887 | if (recv->mad.mad.mad_hdr.mgmt_class == |
1876 | IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { | 1888 | IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { |
1889 | enum smi_forward_action retsmi; | ||
1890 | |||
1877 | if (smi_handle_dr_smp_recv(&recv->mad.smp, | 1891 | if (smi_handle_dr_smp_recv(&recv->mad.smp, |
1878 | port_priv->device->node_type, | 1892 | port_priv->device->node_type, |
1879 | port_priv->port_num, | 1893 | port_num, |
1880 | port_priv->device->phys_port_cnt) == | 1894 | port_priv->device->phys_port_cnt) == |
1881 | IB_SMI_DISCARD) | 1895 | IB_SMI_DISCARD) |
1882 | goto out; | 1896 | goto out; |
1883 | 1897 | ||
1884 | if (smi_check_forward_dr_smp(&recv->mad.smp) == IB_SMI_LOCAL) | 1898 | retsmi = smi_check_forward_dr_smp(&recv->mad.smp); |
1899 | if (retsmi == IB_SMI_LOCAL) | ||
1885 | goto local; | 1900 | goto local; |
1886 | 1901 | ||
1887 | if (smi_handle_dr_smp_send(&recv->mad.smp, | 1902 | if (retsmi == IB_SMI_SEND) { /* don't forward */ |
1888 | port_priv->device->node_type, | 1903 | if (smi_handle_dr_smp_send(&recv->mad.smp, |
1889 | port_priv->port_num) == IB_SMI_DISCARD) | 1904 | port_priv->device->node_type, |
1890 | goto out; | 1905 | port_num) == IB_SMI_DISCARD) |
1906 | goto out; | ||
1907 | |||
1908 | if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD) | ||
1909 | goto out; | ||
1910 | } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) { | ||
1911 | /* forward case for switches */ | ||
1912 | memcpy(response, recv, sizeof(*response)); | ||
1913 | response->header.recv_wc.wc = &response->header.wc; | ||
1914 | response->header.recv_wc.recv_buf.mad = &response->mad.mad; | ||
1915 | response->header.recv_wc.recv_buf.grh = &response->grh; | ||
1916 | |||
1917 | if (!agent_send_response(&response->mad.mad, | ||
1918 | &response->grh, wc, | ||
1919 | port_priv->device, | ||
1920 | smi_get_fwd_port(&recv->mad.smp), | ||
1921 | qp_info->qp->qp_num)) | ||
1922 | response = NULL; | ||
1891 | 1923 | ||
1892 | if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD) | ||
1893 | goto out; | 1924 | goto out; |
1925 | } | ||
1894 | } | 1926 | } |
1895 | 1927 | ||
1896 | local: | 1928 | local: |
@@ -1919,7 +1951,7 @@ local: | |||
1919 | agent_send_response(&response->mad.mad, | 1951 | agent_send_response(&response->mad.mad, |
1920 | &recv->grh, wc, | 1952 | &recv->grh, wc, |
1921 | port_priv->device, | 1953 | port_priv->device, |
1922 | port_priv->port_num, | 1954 | port_num, |
1923 | qp_info->qp->qp_num); | 1955 | qp_info->qp->qp_num); |
1924 | goto out; | 1956 | goto out; |
1925 | } | 1957 | } |
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c index 2bca753eb622..87236753bce9 100644 --- a/drivers/infiniband/core/smi.c +++ b/drivers/infiniband/core/smi.c | |||
@@ -192,7 +192,7 @@ enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, | |||
192 | } | 192 | } |
193 | /* smp->hop_ptr updated when sending */ | 193 | /* smp->hop_ptr updated when sending */ |
194 | return (node_type == RDMA_NODE_IB_SWITCH ? | 194 | return (node_type == RDMA_NODE_IB_SWITCH ? |
195 | IB_SMI_HANDLE: IB_SMI_DISCARD); | 195 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
196 | } | 196 | } |
197 | 197 | ||
198 | /* C14-13:4 -- hop_ptr = 0 -> give to SM */ | 198 | /* C14-13:4 -- hop_ptr = 0 -> give to SM */ |
@@ -211,7 +211,7 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) | |||
211 | if (!ib_get_smp_direction(smp)) { | 211 | if (!ib_get_smp_direction(smp)) { |
212 | /* C14-9:2 -- intermediate hop */ | 212 | /* C14-9:2 -- intermediate hop */ |
213 | if (hop_ptr && hop_ptr < hop_cnt) | 213 | if (hop_ptr && hop_ptr < hop_cnt) |
214 | return IB_SMI_SEND; | 214 | return IB_SMI_FORWARD; |
215 | 215 | ||
216 | /* C14-9:3 -- at the end of the DR segment of path */ | 216 | /* C14-9:3 -- at the end of the DR segment of path */ |
217 | if (hop_ptr == hop_cnt) | 217 | if (hop_ptr == hop_cnt) |
@@ -224,7 +224,7 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) | |||
224 | } else { | 224 | } else { |
225 | /* C14-13:2 -- intermediate hop */ | 225 | /* C14-13:2 -- intermediate hop */ |
226 | if (2 <= hop_ptr && hop_ptr <= hop_cnt) | 226 | if (2 <= hop_ptr && hop_ptr <= hop_cnt) |
227 | return IB_SMI_SEND; | 227 | return IB_SMI_FORWARD; |
228 | 228 | ||
229 | /* C14-13:3 -- at the end of the DR segment of path */ | 229 | /* C14-13:3 -- at the end of the DR segment of path */ |
230 | if (hop_ptr == 1) | 230 | if (hop_ptr == 1) |
@@ -233,3 +233,13 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) | |||
233 | } | 233 | } |
234 | return IB_SMI_LOCAL; | 234 | return IB_SMI_LOCAL; |
235 | } | 235 | } |
236 | |||
237 | /* | ||
238 | * Return the forwarding port number from initial_path for outgoing SMP and | ||
239 | * from return_path for returning SMP | ||
240 | */ | ||
241 | int smi_get_fwd_port(struct ib_smp *smp) | ||
242 | { | ||
243 | return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] : | ||
244 | smp->return_path[smp->hop_ptr-1]); | ||
245 | } | ||
diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h index 9a4b349efc30..1cfc2984434f 100644 --- a/drivers/infiniband/core/smi.h +++ b/drivers/infiniband/core/smi.h | |||
@@ -48,10 +48,12 @@ enum smi_action { | |||
48 | enum smi_forward_action { | 48 | enum smi_forward_action { |
49 | IB_SMI_LOCAL, /* SMP should be completed up the stack */ | 49 | IB_SMI_LOCAL, /* SMP should be completed up the stack */ |
50 | IB_SMI_SEND, /* received DR SMP should be forwarded to the send queue */ | 50 | IB_SMI_SEND, /* received DR SMP should be forwarded to the send queue */ |
51 | IB_SMI_FORWARD /* SMP should be forwarded (for switches only) */ | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, | 54 | enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, |
54 | int port_num, int phys_port_cnt); | 55 | int port_num, int phys_port_cnt); |
56 | int smi_get_fwd_port(struct ib_smp *smp); | ||
55 | extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp); | 57 | extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp); |
56 | extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, | 58 | extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, |
57 | u8 node_type, int port_num); | 59 | u8 node_type, int port_num); |