• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  IBM eServer eHCA Infiniband device driver for Linux on POWER
3  *
4  *  mcast  functions
5  *
6  *  Authors: Khadija Souissi <souissik@de.ibm.com>
7  *           Waleri Fomin <fomin@de.ibm.com>
8  *           Reinhard Ernst <rernst@de.ibm.com>
9  *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
10  *           Heiko J Schick <schickhj@de.ibm.com>
11  *
12  *  Copyright (c) 2005 IBM Corporation
13  *
14  *  All rights reserved.
15  *
16  *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
17  *  BSD.
18  *
19  * OpenIB BSD License
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions are met:
23  *
24  * Redistributions of source code must retain the above copyright notice, this
25  * list of conditions and the following disclaimer.
26  *
27  * Redistributions in binary form must reproduce the above copyright notice,
28  * this list of conditions and the following disclaimer in the documentation
29  * and/or other materials
30  * provided with the distribution.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
36  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
40  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGE.
43  */
44 
45 #include <linux/module.h>
46 #include <linux/err.h>
47 #include "ehca_classes.h"
48 #include "ehca_tools.h"
49 #include "ehca_qes.h"
50 #include "ehca_iverbs.h"
51 #include "hcp_if.h"
52 
53 #define MAX_MC_LID 0xFFFE
54 #define MIN_MC_LID 0xC000	/* Multicast limits */
55 #define EHCA_VALID_MULTICAST_GID(gid)  ((gid)[0] == 0xFF)
56 #define EHCA_VALID_MULTICAST_LID(lid) \
57 	(((lid) >= MIN_MC_LID) && ((lid) <= MAX_MC_LID))
58 
ehca_attach_mcast(struct ib_qp * ibqp,union ib_gid * gid,u16 lid)59 int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
60 {
61 	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
62 	struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
63 					      ib_device);
64 	union ib_gid my_gid;
65 	u64 subnet_prefix, interface_id, h_ret;
66 
67 	if (ibqp->qp_type != IB_QPT_UD) {
68 		ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type);
69 		return -EINVAL;
70 	}
71 
72 	if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
73 		ehca_err(ibqp->device, "invalid mulitcast gid");
74 		return -EINVAL;
75 	} else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
76 		ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
77 		return -EINVAL;
78 	}
79 
80 	memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));
81 
82 	subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
83 	interface_id = be64_to_cpu(my_gid.global.interface_id);
84 	h_ret = hipz_h_attach_mcqp(shca->ipz_hca_handle,
85 				   my_qp->ipz_qp_handle,
86 				   my_qp->galpas.kernel,
87 				   lid, subnet_prefix, interface_id);
88 	if (h_ret != H_SUCCESS)
89 		ehca_err(ibqp->device,
90 			 "ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed "
91 			 "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
92 
93 	return ehca2ib_return_code(h_ret);
94 }
95 
ehca_detach_mcast(struct ib_qp * ibqp,union ib_gid * gid,u16 lid)96 int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
97 {
98 	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
99 	struct ehca_shca *shca = container_of(ibqp->pd->device,
100 					      struct ehca_shca, ib_device);
101 	union ib_gid my_gid;
102 	u64 subnet_prefix, interface_id, h_ret;
103 
104 	if (ibqp->qp_type != IB_QPT_UD) {
105 		ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type);
106 		return -EINVAL;
107 	}
108 
109 	if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
110 		ehca_err(ibqp->device, "invalid mulitcast gid");
111 		return -EINVAL;
112 	} else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
113 		ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
114 		return -EINVAL;
115 	}
116 
117 	memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));
118 
119 	subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
120 	interface_id = be64_to_cpu(my_gid.global.interface_id);
121 	h_ret = hipz_h_detach_mcqp(shca->ipz_hca_handle,
122 				   my_qp->ipz_qp_handle,
123 				   my_qp->galpas.kernel,
124 				   lid, subnet_prefix, interface_id);
125 	if (h_ret != H_SUCCESS)
126 		ehca_err(ibqp->device,
127 			 "ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed "
128 			 "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
129 
130 	return ehca2ib_return_code(h_ret);
131 }
132