Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
0002 /*
0003  * Copyright(c) 2016 - 2019 Intel Corporation.
0004  */
0005 
0006 #include <linux/slab.h>
0007 #include "ah.h"
0008 #include "vt.h" /* for prints */
0009 
0010 /**
0011  * rvt_check_ah - validate the attributes of AH
0012  * @ibdev: the ib device
0013  * @ah_attr: the attributes of the AH
0014  *
0015  * If driver supports a more detailed check_ah function call back to it
0016  * otherwise just check the basics.
0017  *
0018  * Return: 0 on success
0019  */
0020 int rvt_check_ah(struct ib_device *ibdev,
0021          struct rdma_ah_attr *ah_attr)
0022 {
0023     int err;
0024     int port_num = rdma_ah_get_port_num(ah_attr);
0025     struct ib_port_attr port_attr;
0026     struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
0027     u8 ah_flags = rdma_ah_get_ah_flags(ah_attr);
0028     u8 static_rate = rdma_ah_get_static_rate(ah_attr);
0029 
0030     err = ib_query_port(ibdev, port_num, &port_attr);
0031     if (err)
0032         return -EINVAL;
0033     if (port_num < 1 ||
0034         port_num > ibdev->phys_port_cnt)
0035         return -EINVAL;
0036     if (static_rate != IB_RATE_PORT_CURRENT &&
0037         ib_rate_to_mbps(static_rate) < 0)
0038         return -EINVAL;
0039     if ((ah_flags & IB_AH_GRH) &&
0040         rdma_ah_read_grh(ah_attr)->sgid_index >= port_attr.gid_tbl_len)
0041         return -EINVAL;
0042     if (rdi->driver_f.check_ah)
0043         return rdi->driver_f.check_ah(ibdev, ah_attr);
0044     return 0;
0045 }
0046 EXPORT_SYMBOL(rvt_check_ah);
0047 
0048 /**
0049  * rvt_create_ah - create an address handle
0050  * @ibah: the IB address handle
0051  * @init_attr: the attributes of the AH
0052  * @udata: pointer to user's input output buffer information.
0053  *
0054  * This may be called from interrupt context.
0055  *
0056  * Return: 0 on success
0057  */
0058 int rvt_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
0059           struct ib_udata *udata)
0060 {
0061     struct rvt_ah *ah = ibah_to_rvtah(ibah);
0062     struct rvt_dev_info *dev = ib_to_rvt(ibah->device);
0063     unsigned long flags;
0064 
0065     if (rvt_check_ah(ibah->device, init_attr->ah_attr))
0066         return -EINVAL;
0067 
0068     spin_lock_irqsave(&dev->n_ahs_lock, flags);
0069     if (dev->n_ahs_allocated == dev->dparms.props.max_ah) {
0070         spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
0071         return -ENOMEM;
0072     }
0073 
0074     dev->n_ahs_allocated++;
0075     spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
0076 
0077     rdma_copy_ah_attr(&ah->attr, init_attr->ah_attr);
0078 
0079     if (dev->driver_f.notify_new_ah)
0080         dev->driver_f.notify_new_ah(ibah->device,
0081                         init_attr->ah_attr, ah);
0082 
0083     return 0;
0084 }
0085 
0086 /**
0087  * rvt_destroy_ah - Destroy an address handle
0088  * @ibah: address handle
0089  * @destroy_flags: destroy address handle flags (see enum rdma_destroy_ah_flags)
0090  * Return: 0 on success
0091  */
0092 int rvt_destroy_ah(struct ib_ah *ibah, u32 destroy_flags)
0093 {
0094     struct rvt_dev_info *dev = ib_to_rvt(ibah->device);
0095     struct rvt_ah *ah = ibah_to_rvtah(ibah);
0096     unsigned long flags;
0097 
0098     spin_lock_irqsave(&dev->n_ahs_lock, flags);
0099     dev->n_ahs_allocated--;
0100     spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
0101 
0102     rdma_destroy_ah_attr(&ah->attr);
0103     return 0;
0104 }
0105 
0106 /**
0107  * rvt_modify_ah - modify an ah with given attrs
0108  * @ibah: address handle to modify
0109  * @ah_attr: attrs to apply
0110  *
0111  * Return: 0 on success
0112  */
0113 int rvt_modify_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
0114 {
0115     struct rvt_ah *ah = ibah_to_rvtah(ibah);
0116 
0117     if (rvt_check_ah(ibah->device, ah_attr))
0118         return -EINVAL;
0119 
0120     ah->attr = *ah_attr;
0121 
0122     return 0;
0123 }
0124 
0125 /**
0126  * rvt_query_ah - return attrs for ah
0127  * @ibah: address handle to query
0128  * @ah_attr: return info in this
0129  *
0130  * Return: always 0
0131  */
0132 int rvt_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
0133 {
0134     struct rvt_ah *ah = ibah_to_rvtah(ibah);
0135 
0136     *ah_attr = ah->attr;
0137 
0138     return 0;
0139 }