2  *  IBM eServer eHCA Infiniband device driver for Linux on POWER
 
   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>
 
  12  *  Copyright (c) 2005 IBM Corporation
 
  14  *  All rights reserved.
 
  16  *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
 
  21  * Redistribution and use in source and binary forms, with or without
 
  22  * modification, are permitted provided that the following conditions are met:
 
  24  * Redistributions of source code must retain the above copyright notice, this
 
  25  * list of conditions and the following disclaimer.
 
  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.
 
  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.
 
  45 #include <linux/module.h>
 
  46 #include <linux/err.h>
 
  47 #include "ehca_classes.h"
 
  48 #include "ehca_tools.h"
 
  50 #include "ehca_iverbs.h"
 
  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))
 
  59 int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 
  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,
 
  65         u64 subnet_prefix, interface_id, h_ret;
 
  67         if (ibqp->qp_type != IB_QPT_UD) {
 
  68                 ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type);
 
  72         if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
 
  73                 ehca_err(ibqp->device, "invalid mulitcast gid");
 
  75         } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
 
  76                 ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
 
  80         memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));
 
  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,
 
  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=%li", my_qp, ibqp->qp_num, h_ret);
 
  93         return ehca2ib_return_code(h_ret);
 
  96 int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 
  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);
 
 102         u64 subnet_prefix, interface_id, h_ret;
 
 104         if (ibqp->qp_type != IB_QPT_UD) {
 
 105                 ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type);
 
 109         if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
 
 110                 ehca_err(ibqp->device, "invalid mulitcast gid");
 
 112         } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
 
 113                 ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
 
 117         memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));
 
 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=%li", my_qp, ibqp->qp_num, h_ret);
 
 130         return ehca2ib_return_code(h_ret);