linux/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
<<
>>
Prefs
   1/*******************************************************************
   2 * This file is part of the Emulex RoCE Device Driver for          *
   3 * RoCE (RDMA over Converged Ethernet) adapters.                   *
   4 * Copyright (C) 2008-2012 Emulex. All rights reserved.            *
   5 * EMULEX and SLI are trademarks of Emulex.                        *
   6 * www.emulex.com                                                  *
   7 *                                                                 *
   8 * This program is free software; you can redistribute it and/or   *
   9 * modify it under the terms of version 2 of the GNU General       *
  10 * Public License as published by the Free Software Foundation.    *
  11 * This program is distributed in the hope that it will be useful. *
  12 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
  13 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
  14 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
  15 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
  16 * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
  17 * more details, a copy of which can be found in the file COPYING  *
  18 * included with this package.                                     *
  19 *
  20 * Contact Information:
  21 * linux-drivers@emulex.com
  22 *
  23 * Emulex
  24 * 3333 Susan Street
  25 * Costa Mesa, CA 92626
  26 *******************************************************************/
  27
  28#include <net/neighbour.h>
  29#include <net/netevent.h>
  30
  31#include <rdma/ib_addr.h>
  32
  33#include "ocrdma.h"
  34#include "ocrdma_verbs.h"
  35#include "ocrdma_ah.h"
  36#include "ocrdma_hw.h"
  37
  38static inline int set_av_attr(struct ocrdma_ah *ah,
  39                                struct ib_ah_attr *attr, int pdid)
  40{
  41        int status = 0;
  42        u16 vlan_tag; bool vlan_enabled = false;
  43        struct ocrdma_dev *dev = ah->dev;
  44        struct ocrdma_eth_vlan eth;
  45        struct ocrdma_grh grh;
  46        int eth_sz;
  47
  48        memset(&eth, 0, sizeof(eth));
  49        memset(&grh, 0, sizeof(grh));
  50
  51        ah->sgid_index = attr->grh.sgid_index;
  52
  53        vlan_tag = rdma_get_vlan_id(&attr->grh.dgid);
  54        if (vlan_tag && (vlan_tag < 0x1000)) {
  55                eth.eth_type = cpu_to_be16(0x8100);
  56                eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
  57                vlan_tag |= (attr->sl & 7) << 13;
  58                eth.vlan_tag = cpu_to_be16(vlan_tag);
  59                eth_sz = sizeof(struct ocrdma_eth_vlan);
  60                vlan_enabled = true;
  61        } else {
  62                eth.eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
  63                eth_sz = sizeof(struct ocrdma_eth_basic);
  64        }
  65        memcpy(&eth.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
  66        status = ocrdma_resolve_dgid(dev, &attr->grh.dgid, &eth.dmac[0]);
  67        if (status)
  68                return status;
  69        status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index,
  70                        (union ib_gid *)&grh.sgid[0]);
  71        if (status)
  72                return status;
  73
  74        grh.tclass_flow = cpu_to_be32((6 << 28) |
  75                        (attr->grh.traffic_class << 24) |
  76                        attr->grh.flow_label);
  77        /* 0x1b is next header value in GRH */
  78        grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
  79                        (0x1b << 8) | attr->grh.hop_limit);
  80
  81        memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw));
  82        memcpy(&ah->av->eth_hdr, &eth, eth_sz);
  83        memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
  84        if (vlan_enabled)
  85                ah->av->valid |= OCRDMA_AV_VLAN_VALID;
  86        return status;
  87}
  88
  89struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
  90{
  91        u32 *ahid_addr;
  92        int status;
  93        struct ocrdma_ah *ah;
  94        struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
  95        struct ocrdma_dev *dev = pd->dev;
  96
  97        if (!(attr->ah_flags & IB_AH_GRH))
  98                return ERR_PTR(-EINVAL);
  99
 100        ah = kzalloc(sizeof *ah, GFP_ATOMIC);
 101        if (!ah)
 102                return ERR_PTR(-ENOMEM);
 103        ah->dev = pd->dev;
 104
 105        status = ocrdma_alloc_av(dev, ah);
 106        if (status)
 107                goto av_err;
 108        status = set_av_attr(ah, attr, pd->id);
 109        if (status)
 110                goto av_conf_err;
 111
 112        /* if pd is for the user process, pass the ah_id to user space */
 113        if ((pd->uctx) && (pd->uctx->ah_tbl.va)) {
 114                ahid_addr = pd->uctx->ah_tbl.va + attr->dlid;
 115                *ahid_addr = ah->id;
 116        }
 117        return &ah->ibah;
 118
 119av_conf_err:
 120        ocrdma_free_av(dev, ah);
 121av_err:
 122        kfree(ah);
 123        return ERR_PTR(status);
 124}
 125
 126int ocrdma_destroy_ah(struct ib_ah *ibah)
 127{
 128        struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
 129        ocrdma_free_av(ah->dev, ah);
 130        kfree(ah);
 131        return 0;
 132}
 133
 134int ocrdma_query_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
 135{
 136        struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
 137        struct ocrdma_av *av = ah->av;
 138        struct ocrdma_grh *grh;
 139        attr->ah_flags |= IB_AH_GRH;
 140        if (ah->av->valid & Bit(1)) {
 141                grh = (struct ocrdma_grh *)((u8 *)ah->av +
 142                                sizeof(struct ocrdma_eth_vlan));
 143                attr->sl = be16_to_cpu(av->eth_hdr.vlan_tag) >> 13;
 144        } else {
 145                grh = (struct ocrdma_grh *)((u8 *)ah->av +
 146                                        sizeof(struct ocrdma_eth_basic));
 147                attr->sl = 0;
 148        }
 149        memcpy(&attr->grh.dgid.raw[0], &grh->dgid[0], sizeof(grh->dgid));
 150        attr->grh.sgid_index = ah->sgid_index;
 151        attr->grh.hop_limit = be32_to_cpu(grh->pdid_hoplimit) & 0xff;
 152        attr->grh.traffic_class = be32_to_cpu(grh->tclass_flow) >> 24;
 153        attr->grh.flow_label = be32_to_cpu(grh->tclass_flow) & 0x00ffffffff;
 154        return 0;
 155}
 156
 157int ocrdma_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
 158{
 159        /* modify_ah is unsupported */
 160        return -ENOSYS;
 161}
 162
 163int ocrdma_process_mad(struct ib_device *ibdev,
 164                       int process_mad_flags,
 165                       u8 port_num,
 166                       struct ib_wc *in_wc,
 167                       struct ib_grh *in_grh,
 168                       struct ib_mad *in_mad, struct ib_mad *out_mad)
 169{
 170        return IB_MAD_RESULT_SUCCESS;
 171}
 172