root/drivers/infiniband/hw/mlx4/ah.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. create_ib_ah
  2. create_iboe_ah
  3. mlx4_ib_create_ah
  4. mlx4_ib_create_ah_slave
  5. mlx4_ib_query_ah
  6. mlx4_ib_destroy_ah

   1 /*
   2  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
   3  *
   4  * This software is available to you under a choice of one of two
   5  * licenses.  You may choose to be licensed under the terms of the GNU
   6  * General Public License (GPL) Version 2, available from the file
   7  * COPYING in the main directory of this source tree, or the
   8  * OpenIB.org BSD license below:
   9  *
  10  *     Redistribution and use in source and binary forms, with or
  11  *     without modification, are permitted provided that the following
  12  *     conditions are met:
  13  *
  14  *      - Redistributions of source code must retain the above
  15  *        copyright notice, this list of conditions and the following
  16  *        disclaimer.
  17  *
  18  *      - Redistributions in binary form must reproduce the above
  19  *        copyright notice, this list of conditions and the following
  20  *        disclaimer in the documentation and/or other materials
  21  *        provided with the distribution.
  22  *
  23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30  * SOFTWARE.
  31  */
  32 
  33 #include <rdma/ib_addr.h>
  34 #include <rdma/ib_cache.h>
  35 
  36 #include <linux/slab.h>
  37 #include <linux/inet.h>
  38 #include <linux/string.h>
  39 #include <linux/mlx4/driver.h>
  40 
  41 #include "mlx4_ib.h"
  42 
  43 static void create_ib_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
  44 {
  45         struct mlx4_ib_ah *ah = to_mah(ib_ah);
  46         struct mlx4_dev *dev = to_mdev(ib_ah->device)->dev;
  47 
  48         ah->av.ib.port_pd = cpu_to_be32(to_mpd(ib_ah->pd)->pdn |
  49                             (rdma_ah_get_port_num(ah_attr) << 24));
  50         ah->av.ib.g_slid  = rdma_ah_get_path_bits(ah_attr);
  51         ah->av.ib.sl_tclass_flowlabel =
  52                         cpu_to_be32(rdma_ah_get_sl(ah_attr) << 28);
  53         if (rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) {
  54                 const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
  55 
  56                 ah->av.ib.g_slid   |= 0x80;
  57                 ah->av.ib.gid_index = grh->sgid_index;
  58                 ah->av.ib.hop_limit = grh->hop_limit;
  59                 ah->av.ib.sl_tclass_flowlabel |=
  60                         cpu_to_be32((grh->traffic_class << 20) |
  61                                     grh->flow_label);
  62                 memcpy(ah->av.ib.dgid, grh->dgid.raw, 16);
  63         }
  64 
  65         ah->av.ib.dlid = cpu_to_be16(rdma_ah_get_dlid(ah_attr));
  66         if (rdma_ah_get_static_rate(ah_attr)) {
  67                 u8 static_rate = rdma_ah_get_static_rate(ah_attr) +
  68                                         MLX4_STAT_RATE_OFFSET;
  69 
  70                 while (static_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
  71                        !(1 << static_rate & dev->caps.stat_rate_support))
  72                         --static_rate;
  73                 ah->av.ib.stat_rate = static_rate;
  74         }
  75 }
  76 
  77 static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
  78 {
  79         struct mlx4_ib_dev *ibdev = to_mdev(ib_ah->device);
  80         struct mlx4_ib_ah *ah = to_mah(ib_ah);
  81         const struct ib_gid_attr *gid_attr;
  82         struct mlx4_dev *dev = ibdev->dev;
  83         int is_mcast = 0;
  84         struct in6_addr in6;
  85         u16 vlan_tag = 0xffff;
  86         const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
  87         int ret;
  88 
  89         memcpy(&in6, grh->dgid.raw, sizeof(in6));
  90         if (rdma_is_multicast_addr(&in6))
  91                 is_mcast = 1;
  92 
  93         memcpy(ah->av.eth.mac, ah_attr->roce.dmac, ETH_ALEN);
  94         eth_zero_addr(ah->av.eth.s_mac);
  95 
  96         /*
  97          * If sgid_attr is NULL we are being called by mlx4_ib_create_ah_slave
  98          * and we are directly creating an AV for a slave's gid_index.
  99          */
 100         gid_attr = ah_attr->grh.sgid_attr;
 101         if (gid_attr) {
 102                 ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag,
 103                                               &ah->av.eth.s_mac[0]);
 104                 if (ret)
 105                         return ret;
 106 
 107                 ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
 108                 if (ret < 0)
 109                         return ret;
 110                 ah->av.eth.gid_index = ret;
 111         } else {
 112                 /* mlx4_ib_create_ah_slave fills in the s_mac and the vlan */
 113                 ah->av.eth.gid_index = ah_attr->grh.sgid_index;
 114         }
 115 
 116         if (vlan_tag < 0x1000)
 117                 vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
 118         ah->av.eth.port_pd = cpu_to_be32(to_mpd(ib_ah->pd)->pdn |
 119                                          (rdma_ah_get_port_num(ah_attr) << 24));
 120         ah->av.eth.vlan = cpu_to_be16(vlan_tag);
 121         ah->av.eth.hop_limit = grh->hop_limit;
 122         if (rdma_ah_get_static_rate(ah_attr)) {
 123                 ah->av.eth.stat_rate = rdma_ah_get_static_rate(ah_attr) +
 124                                         MLX4_STAT_RATE_OFFSET;
 125                 while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
 126                        !(1 << ah->av.eth.stat_rate & dev->caps.stat_rate_support))
 127                         --ah->av.eth.stat_rate;
 128         }
 129         ah->av.eth.sl_tclass_flowlabel |=
 130                         cpu_to_be32((grh->traffic_class << 20) |
 131                                     grh->flow_label);
 132         /*
 133          * HW requires multicast LID so we just choose one.
 134          */
 135         if (is_mcast)
 136                 ah->av.ib.dlid = cpu_to_be16(0xc000);
 137 
 138         memcpy(ah->av.eth.dgid, grh->dgid.raw, 16);
 139         ah->av.eth.sl_tclass_flowlabel |= cpu_to_be32(rdma_ah_get_sl(ah_attr)
 140                                                       << 29);
 141         return 0;
 142 }
 143 
 144 int mlx4_ib_create_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr,
 145                       u32 flags, struct ib_udata *udata)
 146 
 147 {
 148         if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
 149                 if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH))
 150                         return -EINVAL;
 151                 /*
 152                  * TBD: need to handle the case when we get
 153                  * called in an atomic context and there we
 154                  * might sleep.  We don't expect this
 155                  * currently since we're working with link
 156                  * local addresses which we can translate
 157                  * without going to sleep.
 158                  */
 159                 return create_iboe_ah(ib_ah, ah_attr);
 160         }
 161 
 162         create_ib_ah(ib_ah, ah_attr);
 163         return 0;
 164 }
 165 
 166 int mlx4_ib_create_ah_slave(struct ib_ah *ah, struct rdma_ah_attr *ah_attr,
 167                             int slave_sgid_index, u8 *s_mac, u16 vlan_tag)
 168 {
 169         struct rdma_ah_attr slave_attr = *ah_attr;
 170         struct mlx4_ib_ah *mah = to_mah(ah);
 171         int ret;
 172 
 173         slave_attr.grh.sgid_attr = NULL;
 174         slave_attr.grh.sgid_index = slave_sgid_index;
 175         ret = mlx4_ib_create_ah(ah, &slave_attr, 0, NULL);
 176         if (ret)
 177                 return ret;
 178 
 179         ah->type = ah_attr->type;
 180 
 181         /* get rid of force-loopback bit */
 182         mah->av.ib.port_pd &= cpu_to_be32(0x7FFFFFFF);
 183 
 184         if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE)
 185                 memcpy(mah->av.eth.s_mac, s_mac, 6);
 186 
 187         if (vlan_tag < 0x1000)
 188                 vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
 189         mah->av.eth.vlan = cpu_to_be16(vlan_tag);
 190 
 191         return 0;
 192 }
 193 
 194 int mlx4_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
 195 {
 196         struct mlx4_ib_ah *ah = to_mah(ibah);
 197         int port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
 198 
 199         memset(ah_attr, 0, sizeof *ah_attr);
 200         ah_attr->type = ibah->type;
 201 
 202         if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
 203                 rdma_ah_set_dlid(ah_attr, 0);
 204                 rdma_ah_set_sl(ah_attr,
 205                                be32_to_cpu(ah->av.eth.sl_tclass_flowlabel)
 206                                >> 29);
 207         } else {
 208                 rdma_ah_set_dlid(ah_attr, be16_to_cpu(ah->av.ib.dlid));
 209                 rdma_ah_set_sl(ah_attr,
 210                                be32_to_cpu(ah->av.ib.sl_tclass_flowlabel)
 211                                >> 28);
 212         }
 213 
 214         rdma_ah_set_port_num(ah_attr, port_num);
 215         if (ah->av.ib.stat_rate)
 216                 rdma_ah_set_static_rate(ah_attr,
 217                                         ah->av.ib.stat_rate -
 218                                         MLX4_STAT_RATE_OFFSET);
 219         rdma_ah_set_path_bits(ah_attr, ah->av.ib.g_slid & 0x7F);
 220         if (mlx4_ib_ah_grh_present(ah)) {
 221                 u32 tc_fl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel);
 222 
 223                 rdma_ah_set_grh(ah_attr, NULL,
 224                                 tc_fl & 0xfffff, ah->av.ib.gid_index,
 225                                 ah->av.ib.hop_limit,
 226                                 tc_fl >> 20);
 227                 rdma_ah_set_dgid_raw(ah_attr, ah->av.ib.dgid);
 228         }
 229 
 230         return 0;
 231 }
 232 
 233 void mlx4_ib_destroy_ah(struct ib_ah *ah, u32 flags)
 234 {
 235         return;
 236 }

/* [<][>][^][v][top][bottom][index][help] */