linux/drivers/infiniband/hw/ehca/ehca_mcast.c
<<
>>
Prefs
   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