Path: blob/master/drivers/infiniband/hw/ehca/ehca_mcast.c
15112 views
/*1* IBM eServer eHCA Infiniband device driver for Linux on POWER2*3* mcast functions4*5* Authors: Khadija Souissi <[email protected]>6* Waleri Fomin <[email protected]>7* Reinhard Ernst <[email protected]>8* Hoang-Nam Nguyen <[email protected]>9* Heiko J Schick <[email protected]>10*11* Copyright (c) 2005 IBM Corporation12*13* All rights reserved.14*15* This source code is distributed under a dual license of GPL v2.0 and OpenIB16* BSD.17*18* OpenIB BSD License19*20* Redistribution and use in source and binary forms, with or without21* modification, are permitted provided that the following conditions are met:22*23* Redistributions of source code must retain the above copyright notice, this24* list of conditions and the following disclaimer.25*26* Redistributions in binary form must reproduce the above copyright notice,27* this list of conditions and the following disclaimer in the documentation28* and/or other materials29* provided with the distribution.30*31* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"32* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE33* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE34* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE35* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR36* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF37* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR38* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER39* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)40* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE41* POSSIBILITY OF SUCH DAMAGE.42*/4344#include <linux/module.h>45#include <linux/err.h>46#include "ehca_classes.h"47#include "ehca_tools.h"48#include "ehca_qes.h"49#include "ehca_iverbs.h"50#include "hcp_if.h"5152#define MAX_MC_LID 0xFFFE53#define MIN_MC_LID 0xC000 /* Multicast limits */54#define EHCA_VALID_MULTICAST_GID(gid) ((gid)[0] == 0xFF)55#define EHCA_VALID_MULTICAST_LID(lid) \56(((lid) >= MIN_MC_LID) && ((lid) <= MAX_MC_LID))5758int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)59{60struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);61struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,62ib_device);63union ib_gid my_gid;64u64 subnet_prefix, interface_id, h_ret;6566if (ibqp->qp_type != IB_QPT_UD) {67ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type);68return -EINVAL;69}7071if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {72ehca_err(ibqp->device, "invalid mulitcast gid");73return -EINVAL;74} else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {75ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);76return -EINVAL;77}7879memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));8081subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);82interface_id = be64_to_cpu(my_gid.global.interface_id);83h_ret = hipz_h_attach_mcqp(shca->ipz_hca_handle,84my_qp->ipz_qp_handle,85my_qp->galpas.kernel,86lid, subnet_prefix, interface_id);87if (h_ret != H_SUCCESS)88ehca_err(ibqp->device,89"ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed "90"h_ret=%lli", my_qp, ibqp->qp_num, h_ret);9192return ehca2ib_return_code(h_ret);93}9495int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)96{97struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);98struct ehca_shca *shca = container_of(ibqp->pd->device,99struct ehca_shca, ib_device);100union ib_gid my_gid;101u64 subnet_prefix, interface_id, h_ret;102103if (ibqp->qp_type != IB_QPT_UD) {104ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type);105return -EINVAL;106}107108if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {109ehca_err(ibqp->device, "invalid mulitcast gid");110return -EINVAL;111} else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {112ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);113return -EINVAL;114}115116memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));117118subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);119interface_id = be64_to_cpu(my_gid.global.interface_id);120h_ret = hipz_h_detach_mcqp(shca->ipz_hca_handle,121my_qp->ipz_qp_handle,122my_qp->galpas.kernel,123lid, subnet_prefix, interface_id);124if (h_ret != H_SUCCESS)125ehca_err(ibqp->device,126"ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed "127"h_ret=%lli", my_qp, ibqp->qp_num, h_ret);128129return ehca2ib_return_code(h_ret);130}131132133