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 59int 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 96int 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