aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/agent.c19
-rw-r--r--drivers/infiniband/core/mad.c50
-rw-r--r--drivers/infiniband/core/smi.c16
-rw-r--r--drivers/infiniband/core/smi.h2
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
1896local: 1928local:
@@ -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 */
241int 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 {
48enum smi_forward_action { 48enum 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
53enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, 54enum 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);
56int smi_get_fwd_port(struct ib_smp *smp);
55extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp); 57extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp);
56extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, 58extern 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);