Commit 119a8e70 authored by Kamal Heib's avatar Kamal Heib Committed by Doug Ledford

IB/rdmavt: Add AH to rdmavt

Original patch is from Kamal Heib <kamalh@mellanox.com>. It has
been split into three separate patches. This one for rdmavt,
a follow on for qib, and one for hfi1.

Create datastructure for address handle and implement the
create/destroy/modify/query of address handle for rdmavt.
Reviewed-by: default avatarIra Weiny <ira.weiny@intel.com>
Signed-off-by: default avatarKamal Heib <kamalh@mellanox.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent f2f34211
...@@ -45,7 +45,49 @@ ...@@ -45,7 +45,49 @@
* *
*/ */
#include <linux/slab.h>
#include "ah.h" #include "ah.h"
#include "vt.h" /* for prints */
/**
* rvt_check_ah - validate the attributes of AH
* @ibdev: the ib device
* @ah_attr: the attributes of the AH
*/
int rvt_check_ah(struct ib_device *ibdev,
struct ib_ah_attr *ah_attr)
{
int err;
struct ib_port_attr port_attr;
struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
enum rdma_link_layer link = rdma_port_get_link_layer(ibdev,
ah_attr->port_num);
err = ib_query_port(ibdev, ah_attr->port_num, &port_attr);
if (err)
return -EINVAL;
if (ah_attr->port_num < 1 ||
ah_attr->port_num > ibdev->phys_port_cnt)
return -EINVAL;
if (ah_attr->static_rate != IB_RATE_PORT_CURRENT &&
ib_rate_to_mbps(ah_attr->static_rate) < 0)
return -EINVAL;
if ((ah_attr->ah_flags & IB_AH_GRH) &&
ah_attr->grh.sgid_index >= port_attr.gid_tbl_len)
return -EINVAL;
if (link != IB_LINK_LAYER_ETHERNET) {
if (ah_attr->dlid == 0)
return -EINVAL;
if (ah_attr->dlid >= RVT_MULTICAST_LID_BASE &&
ah_attr->dlid != RVT_PERMISSIVE_LID &&
!(ah_attr->ah_flags & IB_AH_GRH))
return -EINVAL;
}
if (rdi->driver_f.check_ah(ibdev, ah_attr))
return -EINVAL;
return 0;
}
EXPORT_SYMBOL(rvt_check_ah);
/** /**
* rvt_create_ah - create an address handle * rvt_create_ah - create an address handle
...@@ -57,20 +99,68 @@ ...@@ -57,20 +99,68 @@
struct ib_ah *rvt_create_ah(struct ib_pd *pd, struct ib_ah *rvt_create_ah(struct ib_pd *pd,
struct ib_ah_attr *ah_attr) struct ib_ah_attr *ah_attr)
{ {
return ERR_PTR(-EOPNOTSUPP); struct rvt_ah *ah;
struct rvt_dev_info *dev = ib_to_rvt(pd->device);
unsigned long flags;
if (rvt_check_ah(pd->device, ah_attr))
return ERR_PTR(-EINVAL);
ah = kmalloc(sizeof(*ah), GFP_ATOMIC);
if (!ah)
return ERR_PTR(-ENOMEM);
spin_lock_irqsave(&dev->n_ahs_lock, flags);
if (dev->n_ahs_allocated == dev->dparms.props.max_ah) {
spin_unlock(&dev->n_ahs_lock);
kfree(ah);
return ERR_PTR(-ENOMEM);
}
dev->n_ahs_allocated++;
spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
ah->attr = *ah_attr;
atomic_set(&ah->refcount, 0);
return &ah->ibah;
} }
int rvt_destroy_ah(struct ib_ah *ibah) int rvt_destroy_ah(struct ib_ah *ibah)
{ {
return -EOPNOTSUPP; struct rvt_dev_info *dev = ib_to_rvt(ibah->device);
struct rvt_ah *ah = ibah_to_rvtah(ibah);
unsigned long flags;
if (atomic_read(&ah->refcount) != 0)
return -EBUSY;
spin_lock_irqsave(&dev->n_ahs_lock, flags);
dev->n_ahs_allocated--;
spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
kfree(ah);
return 0;
} }
int rvt_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) int rvt_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
{ {
return -EOPNOTSUPP; struct rvt_ah *ah = ibah_to_rvtah(ibah);
if (rvt_check_ah(ibah->device, ah_attr))
return -EINVAL;
ah->attr = *ah_attr;
return 0;
} }
int rvt_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) int rvt_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
{ {
return -EOPNOTSUPP; struct rvt_ah *ah = ibah_to_rvtah(ibah);
*ah_attr = ah->attr;
return 0;
} }
...@@ -221,7 +221,8 @@ int rvt_register_device(struct rvt_dev_info *rdi) ...@@ -221,7 +221,8 @@ int rvt_register_device(struct rvt_dev_info *rdi)
if ((!rdi->driver_f.port_callback) || if ((!rdi->driver_f.port_callback) ||
(!rdi->driver_f.get_card_name) || (!rdi->driver_f.get_card_name) ||
(!rdi->driver_f.get_pci_dev)) { (!rdi->driver_f.get_pci_dev) ||
(!rdi->driver_f.check_ah)) {
return -EINVAL; return -EINVAL;
} }
...@@ -252,6 +253,8 @@ int rvt_register_device(struct rvt_dev_info *rdi) ...@@ -252,6 +253,8 @@ int rvt_register_device(struct rvt_dev_info *rdi)
CHECK_DRIVER_OVERRIDE(rdi, destroy_ah); CHECK_DRIVER_OVERRIDE(rdi, destroy_ah);
CHECK_DRIVER_OVERRIDE(rdi, modify_ah); CHECK_DRIVER_OVERRIDE(rdi, modify_ah);
CHECK_DRIVER_OVERRIDE(rdi, query_ah); CHECK_DRIVER_OVERRIDE(rdi, query_ah);
spin_lock_init(&rdi->n_ahs_lock);
rdi->n_ahs_allocated = 0;
/* Shared Receive Queue */ /* Shared Receive Queue */
CHECK_DRIVER_OVERRIDE(rdi, create_srq); CHECK_DRIVER_OVERRIDE(rdi, create_srq);
......
...@@ -411,6 +411,7 @@ struct rvt_driver_provided { ...@@ -411,6 +411,7 @@ struct rvt_driver_provided {
int (*port_callback)(struct ib_device *, u8, struct kobject *); int (*port_callback)(struct ib_device *, u8, struct kobject *);
const char * (*get_card_name)(struct rvt_dev_info *rdi); const char * (*get_card_name)(struct rvt_dev_info *rdi);
struct pci_dev * (*get_pci_dev)(struct rvt_dev_info *rdi); struct pci_dev * (*get_pci_dev)(struct rvt_dev_info *rdi);
int (*check_ah)(struct ib_device *, struct ib_ah_attr *);
}; };
/* Protection domain */ /* Protection domain */
...@@ -419,6 +420,13 @@ struct rvt_pd { ...@@ -419,6 +420,13 @@ struct rvt_pd {
int user; /* non-zero if created from user space */ int user; /* non-zero if created from user space */
}; };
/* Address handle */
struct rvt_ah {
struct ib_ah ibah;
struct ib_ah_attr attr;
atomic_t refcount;
};
struct rvt_dev_info { struct rvt_dev_info {
struct ib_device ibdev; /* Keep this first. Nothing above here */ struct ib_device ibdev; /* Keep this first. Nothing above here */
...@@ -445,6 +453,9 @@ struct rvt_dev_info { ...@@ -445,6 +453,9 @@ struct rvt_dev_info {
int n_pds_allocated; int n_pds_allocated;
spinlock_t n_pds_lock; /* Protect pd allocated count */ spinlock_t n_pds_lock; /* Protect pd allocated count */
int n_ahs_allocated;
spinlock_t n_ahs_lock; /* Protect ah allocated count */
int flags; int flags;
}; };
...@@ -453,6 +464,11 @@ static inline struct rvt_pd *ibpd_to_rvtpd(struct ib_pd *ibpd) ...@@ -453,6 +464,11 @@ static inline struct rvt_pd *ibpd_to_rvtpd(struct ib_pd *ibpd)
return container_of(ibpd, struct rvt_pd, ibpd); return container_of(ibpd, struct rvt_pd, ibpd);
} }
static inline struct rvt_ah *ibah_to_rvtah(struct ib_ah *ibah)
{
return container_of(ibah, struct rvt_ah, ibah);
}
static inline struct rvt_dev_info *ib_to_rvt(struct ib_device *ibdev) static inline struct rvt_dev_info *ib_to_rvt(struct ib_device *ibdev)
{ {
return container_of(ibdev, struct rvt_dev_info, ibdev); return container_of(ibdev, struct rvt_dev_info, ibdev);
...@@ -471,6 +487,7 @@ static inline void rvt_get_mr(struct rvt_mregion *mr) ...@@ -471,6 +487,7 @@ static inline void rvt_get_mr(struct rvt_mregion *mr)
int rvt_register_device(struct rvt_dev_info *rvd); int rvt_register_device(struct rvt_dev_info *rvd);
void rvt_unregister_device(struct rvt_dev_info *rvd); void rvt_unregister_device(struct rvt_dev_info *rvd);
int rvt_check_ah(struct ib_device *ibdev, struct ib_ah_attr *ah_attr);
int rvt_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge, int rvt_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge,
u32 len, u64 vaddr, u32 rkey, int acc); u32 len, u64 vaddr, u32 rkey, int acc);
int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd, int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment