Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
0031  */
0032 
0033 #include <rdma/ib_addr.h>
0034 #include <rdma/ib_cache.h>
0035 
0036 #include <linux/slab.h>
0037 #include <linux/inet.h>
0038 #include <linux/string.h>
0039 #include <linux/mlx4/driver.h>
0040 
0041 #include "mlx4_ib.h"
0042 
0043 static void create_ib_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
0044 {
0045     struct mlx4_ib_ah *ah = to_mah(ib_ah);
0046     struct mlx4_dev *dev = to_mdev(ib_ah->device)->dev;
0047 
0048     ah->av.ib.port_pd = cpu_to_be32(to_mpd(ib_ah->pd)->pdn |
0049                 (rdma_ah_get_port_num(ah_attr) << 24));
0050     ah->av.ib.g_slid  = rdma_ah_get_path_bits(ah_attr);
0051     ah->av.ib.sl_tclass_flowlabel =
0052             cpu_to_be32(rdma_ah_get_sl(ah_attr) << 28);
0053     if (rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) {
0054         const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
0055 
0056         ah->av.ib.g_slid   |= 0x80;
0057         ah->av.ib.gid_index = grh->sgid_index;
0058         ah->av.ib.hop_limit = grh->hop_limit;
0059         ah->av.ib.sl_tclass_flowlabel |=
0060             cpu_to_be32((grh->traffic_class << 20) |
0061                     grh->flow_label);
0062         memcpy(ah->av.ib.dgid, grh->dgid.raw, 16);
0063     }
0064 
0065     ah->av.ib.dlid = cpu_to_be16(rdma_ah_get_dlid(ah_attr));
0066     if (rdma_ah_get_static_rate(ah_attr)) {
0067         u8 static_rate = rdma_ah_get_static_rate(ah_attr) +
0068                     MLX4_STAT_RATE_OFFSET;
0069 
0070         while (static_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
0071                !(1 << static_rate & dev->caps.stat_rate_support))
0072             --static_rate;
0073         ah->av.ib.stat_rate = static_rate;
0074     }
0075 }
0076 
0077 static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
0078 {
0079     struct mlx4_ib_dev *ibdev = to_mdev(ib_ah->device);
0080     struct mlx4_ib_ah *ah = to_mah(ib_ah);
0081     const struct ib_gid_attr *gid_attr;
0082     struct mlx4_dev *dev = ibdev->dev;
0083     int is_mcast = 0;
0084     struct in6_addr in6;
0085     u16 vlan_tag = 0xffff;
0086     const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
0087     int ret;
0088 
0089     memcpy(&in6, grh->dgid.raw, sizeof(in6));
0090     if (rdma_is_multicast_addr(&in6))
0091         is_mcast = 1;
0092 
0093     memcpy(ah->av.eth.mac, ah_attr->roce.dmac, ETH_ALEN);
0094     eth_zero_addr(ah->av.eth.s_mac);
0095 
0096     /*
0097      * If sgid_attr is NULL we are being called by mlx4_ib_create_ah_slave
0098      * and we are directly creating an AV for a slave's gid_index.
0099      */
0100     gid_attr = ah_attr->grh.sgid_attr;
0101     if (gid_attr) {
0102         ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag,
0103                           &ah->av.eth.s_mac[0]);
0104         if (ret)
0105             return ret;
0106 
0107         ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
0108         if (ret < 0)
0109             return ret;
0110         ah->av.eth.gid_index = ret;
0111     } else {
0112         /* mlx4_ib_create_ah_slave fills in the s_mac and the vlan */
0113         ah->av.eth.gid_index = ah_attr->grh.sgid_index;
0114     }
0115 
0116     if (vlan_tag < 0x1000)
0117         vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
0118     ah->av.eth.port_pd = cpu_to_be32(to_mpd(ib_ah->pd)->pdn |
0119                      (rdma_ah_get_port_num(ah_attr) << 24));
0120     ah->av.eth.vlan = cpu_to_be16(vlan_tag);
0121     ah->av.eth.hop_limit = grh->hop_limit;
0122     if (rdma_ah_get_static_rate(ah_attr)) {
0123         ah->av.eth.stat_rate = rdma_ah_get_static_rate(ah_attr) +
0124                     MLX4_STAT_RATE_OFFSET;
0125         while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
0126                !(1 << ah->av.eth.stat_rate & dev->caps.stat_rate_support))
0127             --ah->av.eth.stat_rate;
0128     }
0129     ah->av.eth.sl_tclass_flowlabel |=
0130             cpu_to_be32((grh->traffic_class << 20) |
0131                     grh->flow_label);
0132     /*
0133      * HW requires multicast LID so we just choose one.
0134      */
0135     if (is_mcast)
0136         ah->av.ib.dlid = cpu_to_be16(0xc000);
0137 
0138     memcpy(ah->av.eth.dgid, grh->dgid.raw, 16);
0139     ah->av.eth.sl_tclass_flowlabel |= cpu_to_be32(rdma_ah_get_sl(ah_attr)
0140                               << 29);
0141     return 0;
0142 }
0143 
0144 int mlx4_ib_create_ah(struct ib_ah *ib_ah, struct rdma_ah_init_attr *init_attr,
0145               struct ib_udata *udata)
0146 {
0147     struct rdma_ah_attr *ah_attr = init_attr->ah_attr;
0148 
0149     if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
0150         if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH))
0151             return -EINVAL;
0152         /*
0153          * TBD: need to handle the case when we get
0154          * called in an atomic context and there we
0155          * might sleep.  We don't expect this
0156          * currently since we're working with link
0157          * local addresses which we can translate
0158          * without going to sleep.
0159          */
0160         return create_iboe_ah(ib_ah, ah_attr);
0161     }
0162 
0163     create_ib_ah(ib_ah, ah_attr);
0164     return 0;
0165 }
0166 
0167 int mlx4_ib_create_ah_slave(struct ib_ah *ah, struct rdma_ah_attr *ah_attr,
0168                 int slave_sgid_index, u8 *s_mac, u16 vlan_tag)
0169 {
0170     struct rdma_ah_attr slave_attr = *ah_attr;
0171     struct rdma_ah_init_attr init_attr = {};
0172     struct mlx4_ib_ah *mah = to_mah(ah);
0173     int ret;
0174 
0175     slave_attr.grh.sgid_attr = NULL;
0176     slave_attr.grh.sgid_index = slave_sgid_index;
0177     init_attr.ah_attr = &slave_attr;
0178     ret = mlx4_ib_create_ah(ah, &init_attr, NULL);
0179     if (ret)
0180         return ret;
0181 
0182     ah->type = ah_attr->type;
0183 
0184     /* get rid of force-loopback bit */
0185     mah->av.ib.port_pd &= cpu_to_be32(0x7FFFFFFF);
0186 
0187     if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE)
0188         memcpy(mah->av.eth.s_mac, s_mac, 6);
0189 
0190     if (vlan_tag < 0x1000)
0191         vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
0192     mah->av.eth.vlan = cpu_to_be16(vlan_tag);
0193 
0194     return 0;
0195 }
0196 
0197 int mlx4_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
0198 {
0199     struct mlx4_ib_ah *ah = to_mah(ibah);
0200     int port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
0201 
0202     memset(ah_attr, 0, sizeof *ah_attr);
0203     ah_attr->type = ibah->type;
0204 
0205     if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
0206         rdma_ah_set_dlid(ah_attr, 0);
0207         rdma_ah_set_sl(ah_attr,
0208                    be32_to_cpu(ah->av.eth.sl_tclass_flowlabel)
0209                    >> 29);
0210     } else {
0211         rdma_ah_set_dlid(ah_attr, be16_to_cpu(ah->av.ib.dlid));
0212         rdma_ah_set_sl(ah_attr,
0213                    be32_to_cpu(ah->av.ib.sl_tclass_flowlabel)
0214                    >> 28);
0215     }
0216 
0217     rdma_ah_set_port_num(ah_attr, port_num);
0218     if (ah->av.ib.stat_rate)
0219         rdma_ah_set_static_rate(ah_attr,
0220                     ah->av.ib.stat_rate -
0221                     MLX4_STAT_RATE_OFFSET);
0222     rdma_ah_set_path_bits(ah_attr, ah->av.ib.g_slid & 0x7F);
0223     if (mlx4_ib_ah_grh_present(ah)) {
0224         u32 tc_fl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel);
0225 
0226         rdma_ah_set_grh(ah_attr, NULL,
0227                 tc_fl & 0xfffff, ah->av.ib.gid_index,
0228                 ah->av.ib.hop_limit,
0229                 tc_fl >> 20);
0230         rdma_ah_set_dgid_raw(ah_attr, ah->av.ib.dgid);
0231     }
0232 
0233     return 0;
0234 }