0001
0002
0003
0004
0005
0006 #include <linux/slab.h>
0007 #include "ah.h"
0008 #include "vt.h" /* for prints */
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
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
0050
0051
0052
0053
0054
0055
0056
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
0088
0089
0090
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
0108
0109
0110
0111
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
0127
0128
0129
0130
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 }