mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
OFED: Various changes from Linux 4.17
This contains changes from the following Linux commits:
a3b641af72ba RDMA/CM: move rdma_id_private to cma_priv.h
6612b4983f7e IB/core: Fix comments of GID query functions
b26c4a1138df IB/{core, ipoib}: Simplify ib_find_gid() for unused ndev
5ac08a341303 IB/cma: Use rdma_protocol_roce() and remove cma_protocol_roce_dev_port()
a9c06aeba997 IB/core: Remove rdma_resolve_ip_route() as exported symbol
a22af59ea9a5 IB/cm: Add and use a helper function to add cm_id's to the port list
cb12a8e2fa5f IB/cm: Introduce and use helper function to get cm_port from path
0a5141593567 IB/core: Refactor ib_init_ah_attr_from_path() for RoCE
e41a7c41947d IB/core: Move rdma_addr_find_l2_eth_by_grh to core_priv.h
98f1f4e0ed26 IB/core: Refer to RoCE port property instead of GID table property
114cc9c4b182 IB/cma: Resolve route only while receiving CM requests
9137108cc3d6 RDMA/rdma_cm: Fix use after free race with process_one_req
190fb9c4d130 IB/core: Refer to RoCE port property to decide building cache
22d24f75a193 IB/core: Search GID only for IB link layer
4ab7cb4bf362 IB/core: Refer to RoCE port property instead of GID table property
3401857ea347 IB/core: Generate GID change event regardless of RoCE GID table property
218b9e3eb8b5 RDMA/cma: Move rdma_cm_state to cma_priv.h
8435168d50e6 RDMA/ucma: Don't allow setting RDMA_OPTION_IB_PATH without an RDMA device
72e1ff0fb7e0 RDMA/core: Update query_gid documentation for HCA drivers
0e1f9b924471 RDMA/providers: Simplify query_gid callback of RoCE providers
598ff6bae689 IB/core: Refactor GID modify code for RoCE
f35faa4ba956 IB/core: Simplify ib_query_gid to always refer to cache
14169e333e71 IB/providers: Avoid zero GID check for RoCE
414448d249d8 RDMA: Use ib_gid_attr during GID modification
ee6548d1d98d RDMA/rdma_cm: Delete rdma_addr_client
44e75052bc2a RDMA/rdma_cm: Make rdma_addr_cancel into a fence
e19c0d237873 RDMA/rdma_cm: Remove process_req and timer sorting
a66ed149b0da IB/core: Don't allow default GID addition at non reseved slots
dc5640f294e4 IB/core: Fix deleting default GIDs when changing mac adddress
22c01ee4b8a8 IB/core: Fix to avoid deleting IPv6 look alike default GIDs
9aa169213d11 RDMA/cma: Do not query GID during QP state transition to RTR
aec05afe641b IB/core: Remove redundant return
Tested by: Wafa Hamzah <[email protected]> (mlx5_ib)
Tested by: John Baldwin <[email protected]> (iw_cxgbe)
Sponsored by: Chelsio Communications
This commit is contained in:
1 parent
1d99feddd6
commit
75cde38e94
28 files changed
+709
-764
No files matched your search
@@ -443,12 +443,11 @@ int bnxt_re_query_gid(struct ib_device *ibdev, u8 port_num,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num,
|
||||
unsigned int index, void **context)
|
||||
int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
|
||||
{
|
||||
int rc = 0;
|
||||
struct bnxt_re_gid_ctx *ctx, **ctx_tbl;
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
|
||||
struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
|
||||
struct bnxt_qplib_gid *gid_to_del;
|
||||
u16 vlan_id = 0xFFFF;
|
||||
@@ -482,14 +481,14 @@ int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num,
|
||||
dev_dbg(rdev_to_dev(rdev),
|
||||
"Trying to delete GID0 while QP1 is alive\n");
|
||||
if (!ctx->refcnt) {
|
||||
rdev->gid_map[index] = -1;
|
||||
rdev->gid_map[attr->index] = -1;
|
||||
ctx_tbl = sgid_tbl->ctx;
|
||||
ctx_tbl[ctx->idx] = NULL;
|
||||
kfree(ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
rdev->gid_map[index] = -1;
|
||||
rdev->gid_map[attr->index] = -1;
|
||||
if (!ctx->refcnt) {
|
||||
rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del,
|
||||
vlan_id, true);
|
||||
@@ -510,15 +509,14 @@ int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnxt_re_add_gid(struct ib_device *ibdev, u8 port_num,
|
||||
unsigned int index, const union ib_gid *gid,
|
||||
int bnxt_re_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr, void **context)
|
||||
{
|
||||
int rc;
|
||||
u32 tbl_idx = 0;
|
||||
u16 vlan_id = 0xFFFF;
|
||||
struct bnxt_re_gid_ctx *ctx, **ctx_tbl;
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
|
||||
struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
|
||||
if ((attr->ndev) && is_vlan_dev(attr->ndev))
|
||||
vlan_id = vlan_dev_vlan_id(attr->ndev);
|
||||
@@ -540,8 +538,8 @@ int bnxt_re_add_gid(struct ib_device *ibdev, u8 port_num,
|
||||
ctx_tbl[tbl_idx]->refcnt++;
|
||||
}
|
||||
*context = ctx_tbl[tbl_idx];
|
||||
/* tbl_idx is the HW table index and index is the stack index */
|
||||
rdev->gid_map[index] = tbl_idx;
|
||||
/* tbl_idx is the HW table index and attr->index is the stack index */
|
||||
rdev->gid_map[attr->index] = tbl_idx;
|
||||
return 0;
|
||||
} else if (rc < 0) {
|
||||
dev_err(rdev_to_dev(rdev), "Add GID failed rc = 0x%x\n", rc);
|
||||
@@ -556,8 +554,8 @@ int bnxt_re_add_gid(struct ib_device *ibdev, u8 port_num,
|
||||
ctx->idx = tbl_idx;
|
||||
ctx->refcnt = 1;
|
||||
ctx_tbl[tbl_idx] = ctx;
|
||||
/* tbl_idx is the HW table index and index is the stack index */
|
||||
rdev->gid_map[index] = tbl_idx;
|
||||
/* tbl_idx is the HW table index and attr->index is the stack index */
|
||||
rdev->gid_map[attr->index] = tbl_idx;
|
||||
*context = ctx;
|
||||
}
|
||||
return rc;
|
||||
|
||||
@@ -295,10 +295,8 @@ int bnxt_re_get_port_immutable(struct ib_device *ibdev, u8 port_num,
|
||||
void bnxt_re_compat_qfwstr(void);
|
||||
int bnxt_re_query_pkey(struct ib_device *ibdev, u8 port_num,
|
||||
u16 index, u16 *pkey);
|
||||
int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num,
|
||||
unsigned int index, void **context);
|
||||
int bnxt_re_add_gid(struct ib_device *ibdev, u8 port_num,
|
||||
unsigned int index, const union ib_gid *gid,
|
||||
int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context);
|
||||
int bnxt_re_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr, void **context);
|
||||
int bnxt_re_query_gid(struct ib_device *ibdev, u8 port_num,
|
||||
int index, union ib_gid *gid);
|
||||
|
||||
@@ -2179,7 +2179,6 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
|
||||
ibdev->modify_port = bnxt_re_modify_port;
|
||||
ibdev->get_port_immutable = bnxt_re_get_port_immutable;
|
||||
ibdev->query_pkey = bnxt_re_query_pkey;
|
||||
ibdev->query_gid = bnxt_re_query_gid;
|
||||
ibdev->get_netdev = bnxt_re_get_netdev;
|
||||
ibdev->add_gid = bnxt_re_add_gid;
|
||||
ibdev->del_gid = bnxt_re_del_gid;
|
||||
|
||||
@@ -156,8 +156,6 @@ int irdma_iw_port_immutable(struct ib_device *ibdev, u8 port_num,
|
||||
struct ib_port_immutable *immutable);
|
||||
int irdma_query_gid(struct ib_device *ibdev, u8 port, int index,
|
||||
union ib_gid *gid);
|
||||
int irdma_query_gid_roce(struct ib_device *ibdev, u8 port, int index,
|
||||
union ib_gid *gid);
|
||||
int irdma_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
|
||||
u16 *pkey);
|
||||
int irdma_query_port(struct ib_device *ibdev, u8 port,
|
||||
@@ -255,9 +253,9 @@ int irdma_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata);
|
||||
void irdma_dealloc_ucontext(struct ib_ucontext *context);
|
||||
int irdma_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
|
||||
void irdma_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
|
||||
int irdma_add_gid(struct ib_device *, u8, unsigned int, const union ib_gid *,
|
||||
int irdma_add_gid(const union ib_gid *,
|
||||
const struct ib_gid_attr *, void **);
|
||||
int irdma_del_gid(struct ib_device *, u8, unsigned int, void **);
|
||||
int irdma_del_gid(const struct ib_gid_attr *, void **);
|
||||
struct ib_device *ib_device_get_by_netdev(struct ifnet *ndev, int driver_id);
|
||||
void ib_device_put(struct ib_device *device);
|
||||
void ib_unregister_device_put(struct ib_device *device);
|
||||
|
||||
@@ -77,10 +77,7 @@ irdma_get_dev_fw_str(struct ib_device *dev,
|
||||
}
|
||||
|
||||
int
|
||||
irdma_add_gid(struct ib_device *device,
|
||||
u8 port_num,
|
||||
unsigned int index,
|
||||
const union ib_gid *gid,
|
||||
irdma_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
void **context)
|
||||
{
|
||||
@@ -88,9 +85,7 @@ irdma_add_gid(struct ib_device *device,
|
||||
}
|
||||
|
||||
int
|
||||
irdma_del_gid(struct ib_device *device,
|
||||
u8 port_num,
|
||||
unsigned int index,
|
||||
irdma_del_gid(const struct ib_gid_attr *attr,
|
||||
void **context)
|
||||
{
|
||||
return 0;
|
||||
@@ -1516,28 +1511,6 @@ ib_unregister_device_put(struct ib_device *device)
|
||||
ib_unregister_device(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* irdma_query_gid_roce - Query port GID for Roce
|
||||
* @ibdev: device pointer from stack
|
||||
* @port: port number
|
||||
* @index: Entry index
|
||||
* @gid: Global ID
|
||||
*/
|
||||
int
|
||||
irdma_query_gid_roce(struct ib_device *ibdev, u8 port, int index,
|
||||
union ib_gid *gid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ib_get_cached_gid(ibdev, port, index, gid, NULL);
|
||||
if (ret == -EAGAIN) {
|
||||
memcpy(gid, &zgid, sizeof(*gid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* irdma_modify_port - modify port attributes
|
||||
* @ibdev: device pointer from stack
|
||||
|
||||
@@ -3328,7 +3328,6 @@ irdma_set_device_roce_ops(struct ib_device *ibdev)
|
||||
dev_ops->get_port_immutable = irdma_roce_port_immutable;
|
||||
dev_ops->modify_qp = irdma_modify_qp_roce;
|
||||
dev_ops->query_ah = irdma_query_ah;
|
||||
dev_ops->query_gid = irdma_query_gid_roce;
|
||||
dev_ops->query_pkey = irdma_query_pkey;
|
||||
ibdev->add_gid = irdma_add_gid;
|
||||
ibdev->del_gid = irdma_del_gid;
|
||||
|
||||
@@ -252,14 +252,11 @@ static int mlx4_ib_update_gids(struct gid_entry *gids,
|
||||
return mlx4_ib_update_gids_v1(gids, ibdev, port_num);
|
||||
}
|
||||
|
||||
static int mlx4_ib_add_gid(struct ib_device *device,
|
||||
u8 port_num,
|
||||
unsigned int index,
|
||||
const union ib_gid *gid,
|
||||
static int mlx4_ib_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
void **context)
|
||||
{
|
||||
struct mlx4_ib_dev *ibdev = to_mdev(device);
|
||||
struct mlx4_ib_dev *ibdev = to_mdev(attr->device);
|
||||
struct mlx4_ib_iboe *iboe = &ibdev->iboe;
|
||||
struct mlx4_port_gid_table *port_gid_table;
|
||||
int free = -1, found = -1;
|
||||
@@ -268,16 +265,16 @@ static int mlx4_ib_add_gid(struct ib_device *device,
|
||||
int i;
|
||||
struct gid_entry *gids = NULL;
|
||||
|
||||
if (!rdma_cap_roce_gid_table(device, port_num))
|
||||
if (!rdma_cap_roce_gid_table(attr->device, attr->port_num))
|
||||
return -EINVAL;
|
||||
|
||||
if (port_num > MLX4_MAX_PORTS)
|
||||
if (attr->port_num > MLX4_MAX_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
if (!context)
|
||||
return -EINVAL;
|
||||
|
||||
port_gid_table = &iboe->gids[port_num - 1];
|
||||
port_gid_table = &iboe->gids[attr->port_num - 1];
|
||||
spin_lock_bh(&iboe->lock);
|
||||
for (i = 0; i < MLX4_MAX_PORT_GIDS; ++i) {
|
||||
if (!memcmp(&port_gid_table->gids[i].gid, gid, sizeof(*gid)) &&
|
||||
@@ -324,33 +321,30 @@ static int mlx4_ib_add_gid(struct ib_device *device,
|
||||
spin_unlock_bh(&iboe->lock);
|
||||
|
||||
if (!ret && hw_update) {
|
||||
ret = mlx4_ib_update_gids(gids, ibdev, port_num);
|
||||
ret = mlx4_ib_update_gids(gids, ibdev, attr->port_num);
|
||||
kfree(gids);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mlx4_ib_del_gid(struct ib_device *device,
|
||||
u8 port_num,
|
||||
unsigned int index,
|
||||
void **context)
|
||||
static int mlx4_ib_del_gid(const struct ib_gid_attr *attr, void **context)
|
||||
{
|
||||
struct gid_cache_context *ctx = *context;
|
||||
struct mlx4_ib_dev *ibdev = to_mdev(device);
|
||||
struct mlx4_ib_dev *ibdev = to_mdev(attr->device);
|
||||
struct mlx4_ib_iboe *iboe = &ibdev->iboe;
|
||||
struct mlx4_port_gid_table *port_gid_table;
|
||||
int ret = 0;
|
||||
int hw_update = 0;
|
||||
struct gid_entry *gids = NULL;
|
||||
|
||||
if (!rdma_cap_roce_gid_table(device, port_num))
|
||||
if (!rdma_cap_roce_gid_table(attr->device, attr->port_num))
|
||||
return -EINVAL;
|
||||
|
||||
if (port_num > MLX4_MAX_PORTS)
|
||||
if (attr->port_num > MLX4_MAX_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
port_gid_table = &iboe->gids[port_num - 1];
|
||||
port_gid_table = &iboe->gids[attr->port_num - 1];
|
||||
spin_lock_bh(&iboe->lock);
|
||||
if (ctx) {
|
||||
ctx->refcount--;
|
||||
@@ -382,7 +376,7 @@ static int mlx4_ib_del_gid(struct ib_device *device,
|
||||
spin_unlock_bh(&iboe->lock);
|
||||
|
||||
if (!ret && hw_update) {
|
||||
ret = mlx4_ib_update_gids(gids, ibdev, port_num);
|
||||
ret = mlx4_ib_update_gids(gids, ibdev, attr->port_num);
|
||||
kfree(gids);
|
||||
}
|
||||
return ret;
|
||||
@@ -417,9 +411,6 @@ int mlx4_ib_gid_index_to_real_index(struct mlx4_ib_dev *ibdev,
|
||||
if (attr.ndev)
|
||||
if_rele(attr.ndev);
|
||||
|
||||
if (!memcmp(&gid, &zgid, sizeof(gid)))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&iboe->lock, flags);
|
||||
port_gid_table = &iboe->gids[port_num - 1];
|
||||
|
||||
@@ -825,24 +816,10 @@ out:
|
||||
static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
|
||||
union ib_gid *gid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (rdma_protocol_ib(ibdev, port))
|
||||
return __mlx4_ib_query_gid(ibdev, port, index, gid, 0);
|
||||
|
||||
if (!rdma_protocol_roce(ibdev, port))
|
||||
return -ENODEV;
|
||||
|
||||
if (!rdma_cap_roce_gid_table(ibdev, port))
|
||||
return -ENODEV;
|
||||
|
||||
ret = ib_get_cached_gid(ibdev, port, index, gid, NULL);
|
||||
if (ret == -EAGAIN) {
|
||||
memcpy(gid, &zgid, sizeof(*gid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx4_ib_query_sl2vl(struct ib_device *ibdev, u8 port, u64 *sl2vl_tbl)
|
||||
|
||||
@@ -1787,8 +1787,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
|
||||
status = ib_get_cached_gid(ibqp->device, port_num,
|
||||
index, &gid, &gid_attr);
|
||||
if (!status && !memcmp(&gid, &zgid, sizeof(gid)))
|
||||
status = -ENOENT;
|
||||
if (!status && gid_attr.ndev) {
|
||||
vlan = rdma_vlan_dev_vlan_id(gid_attr.ndev);
|
||||
memcpy(smac, if_getlladdr(gid_attr.ndev), ETH_ALEN);
|
||||
|
||||
@@ -428,18 +428,19 @@ static int set_roce_addr(struct ib_device *device, u8 port_num,
|
||||
return mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
|
||||
}
|
||||
|
||||
static int mlx5_ib_add_gid(struct ib_device *device, u8 port_num,
|
||||
unsigned int index, const union ib_gid *gid,
|
||||
static int mlx5_ib_add_gid(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
__always_unused void **context)
|
||||
{
|
||||
return set_roce_addr(device, port_num, index, gid, attr);
|
||||
return set_roce_addr(attr->device, attr->port_num, attr->index, gid,
|
||||
attr);
|
||||
}
|
||||
|
||||
static int mlx5_ib_del_gid(struct ib_device *device, u8 port_num,
|
||||
unsigned int index, __always_unused void **context)
|
||||
static int mlx5_ib_del_gid(const struct ib_gid_attr *attr,
|
||||
__always_unused void **context)
|
||||
{
|
||||
return set_roce_addr(device, port_num, index, NULL, NULL);
|
||||
return set_roce_addr(attr->device, attr->port_num, attr->index, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
__be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev, u8 port_num,
|
||||
|
||||
@@ -197,7 +197,6 @@ qlnxr_register_device(qlnxr_dev_t *dev)
|
||||
ibdev->query_gid = qlnxr_iw_query_gid;
|
||||
} else {
|
||||
ibdev->node_type = RDMA_NODE_IB_CA;
|
||||
ibdev->query_gid = qlnxr_query_gid;
|
||||
ibdev->uverbs_cmd_mask |=
|
||||
(1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
|
||||
(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
|
||||
|
||||
@@ -118,44 +118,6 @@ qlnxr_iw_query_gid(struct ib_device *ibdev, u8 port, int index,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
qlnxr_query_gid(struct ib_device *ibdev, u8 port, int index,
|
||||
union ib_gid *sgid)
|
||||
{
|
||||
struct qlnxr_dev *dev;
|
||||
qlnx_host_t *ha;
|
||||
|
||||
dev = get_qlnxr_dev(ibdev);
|
||||
ha = dev->ha;
|
||||
QL_DPRINT12(ha, "enter index: %d\n", index);
|
||||
#if 0
|
||||
int ret = 0;
|
||||
/* @@@: if DEFINE_ROCE_GID_TABLE to be used here */
|
||||
//if (!rdma_cap_roce_gid_table(ibdev, port)) {
|
||||
if (!(rdma_protocol_roce(ibdev, port) &&
|
||||
ibdev->add_gid && ibdev->del_gid)) {
|
||||
QL_DPRINT11(ha, "acquire gid failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = ib_get_cached_gid(ibdev, port, index, sgid, NULL);
|
||||
if (ret == -EAGAIN) {
|
||||
memcpy(sgid, &zgid, sizeof(*sgid));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((index >= QLNXR_MAX_SGID) || (index < 0)) {
|
||||
QL_DPRINT12(ha, "invalid gid index %d\n", index);
|
||||
memset(sgid, 0, sizeof(*sgid));
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(sgid, &dev->sgid_tbl[index], sizeof(*sgid));
|
||||
|
||||
QL_DPRINT12(ha, "exit : %p\n", sgid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
qlnxr_create_srq(struct ib_srq *ibsrq,
|
||||
struct ib_srq_init_attr *init_attr,
|
||||
|
||||
@@ -34,11 +34,6 @@ extern int qlnxr_iw_query_gid(struct ib_device *,
|
||||
int index,
|
||||
union ib_gid *gid);
|
||||
|
||||
extern int qlnxr_query_gid(struct ib_device *,
|
||||
u8 port,
|
||||
int index,
|
||||
union ib_gid *gid);
|
||||
|
||||
extern int qlnxr_create_srq(struct ib_srq *ibsrq,
|
||||
struct ib_srq_init_attr *,
|
||||
struct ib_udata *);
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Voltaire Inc. All rights reserved.
|
||||
* Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
|
||||
* Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
|
||||
* Copyright (c) 2005-2006 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CMA_PRIV_H
|
||||
#define _CMA_PRIV_H
|
||||
|
||||
enum rdma_cm_state {
|
||||
RDMA_CM_IDLE,
|
||||
RDMA_CM_ADDR_QUERY,
|
||||
RDMA_CM_ADDR_RESOLVED,
|
||||
RDMA_CM_ROUTE_QUERY,
|
||||
RDMA_CM_ROUTE_RESOLVED,
|
||||
RDMA_CM_CONNECT,
|
||||
RDMA_CM_DISCONNECT,
|
||||
RDMA_CM_ADDR_BOUND,
|
||||
RDMA_CM_LISTEN,
|
||||
RDMA_CM_DEVICE_REMOVAL,
|
||||
RDMA_CM_DESTROYING
|
||||
};
|
||||
|
||||
struct rdma_id_private {
|
||||
struct rdma_cm_id id;
|
||||
|
||||
struct rdma_bind_list *bind_list;
|
||||
struct hlist_node node;
|
||||
struct list_head list; /* listen_any_list or cma_device.list */
|
||||
struct list_head listen_list; /* per device listens */
|
||||
struct cma_device *cma_dev;
|
||||
struct list_head mc_list;
|
||||
|
||||
int internal_id;
|
||||
enum rdma_cm_state state;
|
||||
spinlock_t lock;
|
||||
struct mutex qp_mutex;
|
||||
|
||||
struct completion comp;
|
||||
atomic_t refcount;
|
||||
struct mutex handler_mutex;
|
||||
|
||||
int backlog;
|
||||
int timeout_ms;
|
||||
struct ib_sa_query *query;
|
||||
int query_id;
|
||||
union {
|
||||
struct ib_cm_id *ib;
|
||||
struct iw_cm_id *iw;
|
||||
} cm_id;
|
||||
|
||||
u32 seq_num;
|
||||
u32 qkey;
|
||||
u32 qp_num;
|
||||
pid_t owner;
|
||||
u32 options;
|
||||
u8 srq;
|
||||
u8 tos;
|
||||
u8 tos_set:1;
|
||||
u8 timeout_set:1;
|
||||
u8 reuseaddr;
|
||||
u8 afonly;
|
||||
u8 timeout;
|
||||
enum ib_gid_type gid_type;
|
||||
};
|
||||
#endif /* _CMA_PRIV_H */
|
||||
@@ -183,6 +183,16 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
|
||||
return qp;
|
||||
}
|
||||
|
||||
struct rdma_dev_addr;
|
||||
int rdma_resolve_ip_route(struct sockaddr *src_addr,
|
||||
const struct sockaddr *dst_addr,
|
||||
struct rdma_dev_addr *addr);
|
||||
|
||||
int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
|
||||
const union ib_gid *dgid,
|
||||
u8 *dmac, if_t ndev,
|
||||
int *hoplimit);
|
||||
|
||||
struct rdma_umap_priv {
|
||||
struct vm_area_struct *vma;
|
||||
struct list_head list;
|
||||
|
||||
@@ -61,7 +61,6 @@ struct addr_req {
|
||||
struct sockaddr_storage src_addr;
|
||||
struct sockaddr_storage dst_addr;
|
||||
struct rdma_dev_addr *addr;
|
||||
struct rdma_addr_client *client;
|
||||
void *context;
|
||||
void (*callback)(int status, struct sockaddr *src_addr,
|
||||
struct rdma_dev_addr *addr, void *context);
|
||||
@@ -70,11 +69,8 @@ struct addr_req {
|
||||
int status;
|
||||
};
|
||||
|
||||
static void process_req(struct work_struct *work);
|
||||
|
||||
static DEFINE_MUTEX(lock);
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
static LIST_HEAD(req_list);
|
||||
static DECLARE_DELAYED_WORK(work, process_req);
|
||||
static struct workqueue_struct *addr_wq;
|
||||
|
||||
int rdma_addr_size(struct sockaddr *addr)
|
||||
@@ -108,28 +104,6 @@ int rdma_addr_size_kss(struct sockaddr_storage *addr)
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_addr_size_kss);
|
||||
|
||||
static struct rdma_addr_client self;
|
||||
|
||||
void rdma_addr_register_client(struct rdma_addr_client *client)
|
||||
{
|
||||
atomic_set(&client->refcount, 1);
|
||||
init_completion(&client->comp);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_addr_register_client);
|
||||
|
||||
static inline void put_client(struct rdma_addr_client *client)
|
||||
{
|
||||
if (atomic_dec_and_test(&client->refcount))
|
||||
complete(&client->comp);
|
||||
}
|
||||
|
||||
void rdma_addr_unregister_client(struct rdma_addr_client *client)
|
||||
{
|
||||
put_client(client);
|
||||
wait_for_completion(&client->comp);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_addr_unregister_client);
|
||||
|
||||
static inline void
|
||||
rdma_copy_addr_sub(u8 *dst, const u8 *src, unsigned min, unsigned max)
|
||||
{
|
||||
@@ -211,7 +185,7 @@ int rdma_translate_ip(const struct sockaddr *addr,
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_translate_ip);
|
||||
|
||||
static void set_timeout(struct delayed_work *delayed_work, unsigned long time)
|
||||
static void set_timeout(struct addr_req *req, unsigned long time)
|
||||
{
|
||||
unsigned long delay;
|
||||
|
||||
@@ -221,23 +195,15 @@ static void set_timeout(struct delayed_work *delayed_work, unsigned long time)
|
||||
else if (delay > hz)
|
||||
delay = hz;
|
||||
|
||||
mod_delayed_work(addr_wq, delayed_work, delay);
|
||||
mod_delayed_work(addr_wq, &req->work, delay);
|
||||
}
|
||||
|
||||
static void queue_req(struct addr_req *req)
|
||||
{
|
||||
struct addr_req *temp_req;
|
||||
|
||||
mutex_lock(&lock);
|
||||
list_for_each_entry_reverse(temp_req, &req_list, list) {
|
||||
if (time_after_eq(req->timeout, temp_req->timeout))
|
||||
break;
|
||||
}
|
||||
|
||||
list_add(&req->list, &temp_req->list);
|
||||
|
||||
set_timeout(&req->work, req->timeout);
|
||||
mutex_unlock(&lock);
|
||||
spin_lock_bh(&lock);
|
||||
list_add_tail(&req->list, &req_list);
|
||||
set_timeout(req, req->timeout);
|
||||
spin_unlock_bh(&lock);
|
||||
}
|
||||
|
||||
#if defined(INET) || defined(INET6)
|
||||
@@ -714,7 +680,6 @@ static void process_one_req(struct work_struct *_work)
|
||||
struct addr_req *req;
|
||||
struct sockaddr *src_in, *dst_in;
|
||||
|
||||
mutex_lock(&lock);
|
||||
req = container_of(_work, struct addr_req, work.work);
|
||||
|
||||
if (req->status == -ENODATA) {
|
||||
@@ -725,62 +690,33 @@ static void process_one_req(struct work_struct *_work)
|
||||
req->status = -ETIMEDOUT;
|
||||
} else if (req->status == -ENODATA) {
|
||||
/* requeue the work for retrying again */
|
||||
set_timeout(&req->work, req->timeout);
|
||||
mutex_unlock(&lock);
|
||||
spin_lock_bh(&lock);
|
||||
if (!list_empty(&req->list))
|
||||
set_timeout(req, req->timeout);
|
||||
spin_unlock_bh(&lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
list_del(&req->list);
|
||||
mutex_unlock(&lock);
|
||||
|
||||
req->callback(req->status, (struct sockaddr *)&req->src_addr,
|
||||
req->addr, req->context);
|
||||
put_client(req->client);
|
||||
kfree(req);
|
||||
}
|
||||
req->callback = NULL;
|
||||
|
||||
static void process_req(struct work_struct *work)
|
||||
{
|
||||
struct addr_req *req, *temp_req;
|
||||
struct sockaddr *src_in, *dst_in;
|
||||
struct list_head done_list;
|
||||
|
||||
INIT_LIST_HEAD(&done_list);
|
||||
|
||||
mutex_lock(&lock);
|
||||
list_for_each_entry_safe(req, temp_req, &req_list, list) {
|
||||
if (req->status == -ENODATA) {
|
||||
src_in = (struct sockaddr *) &req->src_addr;
|
||||
dst_in = (struct sockaddr *) &req->dst_addr;
|
||||
req->status = addr_resolve(src_in, dst_in, req->addr);
|
||||
if (req->status && time_after_eq(jiffies, req->timeout))
|
||||
req->status = -ETIMEDOUT;
|
||||
else if (req->status == -ENODATA) {
|
||||
set_timeout(&req->work, req->timeout);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
list_move_tail(&req->list, &done_list);
|
||||
}
|
||||
|
||||
mutex_unlock(&lock);
|
||||
|
||||
list_for_each_entry_safe(req, temp_req, &done_list, list) {
|
||||
list_del(&req->list);
|
||||
/* It is safe to cancel other work items from this work item
|
||||
* because at a time there can be only one work item running
|
||||
* with this single threaded work queue.
|
||||
spin_lock_bh(&lock);
|
||||
if (!list_empty(&req->list)) {
|
||||
/*
|
||||
* Although the work will normally have been canceled by the
|
||||
* workqueue, it can still be requeued as long as it is on the
|
||||
* req_list.
|
||||
*/
|
||||
cancel_delayed_work(&req->work);
|
||||
req->callback(req->status, (struct sockaddr *) &req->src_addr,
|
||||
req->addr, req->context);
|
||||
put_client(req->client);
|
||||
list_del_init(&req->list);
|
||||
kfree(req);
|
||||
}
|
||||
spin_unlock_bh(&lock);
|
||||
}
|
||||
|
||||
int rdma_resolve_ip(struct rdma_addr_client *client,
|
||||
struct sockaddr *src_addr, struct sockaddr *dst_addr,
|
||||
int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
|
||||
struct rdma_dev_addr *addr, int timeout_ms,
|
||||
void (*callback)(int status, struct sockaddr *src_addr,
|
||||
struct rdma_dev_addr *addr, void *context),
|
||||
@@ -812,8 +748,6 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
|
||||
req->addr = addr;
|
||||
req->callback = callback;
|
||||
req->context = context;
|
||||
req->client = client;
|
||||
atomic_inc(&client->refcount);
|
||||
INIT_DELAYED_WORK(&req->work, process_one_req);
|
||||
|
||||
req->status = addr_resolve(src_in, dst_in, addr);
|
||||
@@ -828,7 +762,6 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
|
||||
break;
|
||||
default:
|
||||
ret = req->status;
|
||||
atomic_dec(&client->refcount);
|
||||
goto err;
|
||||
}
|
||||
return ret;
|
||||
@@ -856,23 +789,40 @@ int rdma_resolve_ip_route(struct sockaddr *src_addr,
|
||||
|
||||
return addr_resolve(src_in, dst_addr, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_resolve_ip_route);
|
||||
|
||||
void rdma_addr_cancel(struct rdma_dev_addr *addr)
|
||||
{
|
||||
struct addr_req *req, *temp_req;
|
||||
struct addr_req *found = NULL;
|
||||
|
||||
mutex_lock(&lock);
|
||||
spin_lock_bh(&lock);
|
||||
list_for_each_entry_safe(req, temp_req, &req_list, list) {
|
||||
if (req->addr == addr) {
|
||||
req->status = -ECANCELED;
|
||||
req->timeout = jiffies;
|
||||
list_move(&req->list, &req_list);
|
||||
set_timeout(&req->work, req->timeout);
|
||||
/*
|
||||
* Removing from the list means we take ownership of
|
||||
* the req
|
||||
*/
|
||||
list_del_init(&req->list);
|
||||
found = req;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&lock);
|
||||
spin_unlock_bh(&lock);
|
||||
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
/*
|
||||
* sync canceling the work after removing it from the req_list
|
||||
* guarentees no work is running and none will be started.
|
||||
*/
|
||||
cancel_delayed_work_sync(&found->work);
|
||||
|
||||
if (found->callback)
|
||||
found->callback(-ECANCELED, (struct sockaddr *)&found->src_addr,
|
||||
found->addr, found->context);
|
||||
|
||||
kfree(found);
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_addr_cancel);
|
||||
|
||||
@@ -907,8 +857,8 @@ int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
|
||||
dev_addr.net = dev_net(ndev);
|
||||
|
||||
init_completion(&ctx.comp);
|
||||
ret = rdma_resolve_ip(&self, &sgid_addr._sockaddr, &dgid_addr._sockaddr,
|
||||
&dev_addr, 1000, resolve_cb, &ctx);
|
||||
ret = rdma_resolve_ip(&sgid_addr._sockaddr, &dgid_addr._sockaddr,
|
||||
&dev_addr, 1000, resolve_cb, &ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -929,13 +879,11 @@ int addr_init(void)
|
||||
if (!addr_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
rdma_addr_register_client(&self);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void addr_cleanup(void)
|
||||
{
|
||||
rdma_addr_unregister_client(&self);
|
||||
destroy_workqueue(addr_wq);
|
||||
WARN_ON(!list_empty(&req_list));
|
||||
}
|
||||
@@ -62,8 +62,6 @@ struct ib_update_work {
|
||||
union ib_gid zgid;
|
||||
EXPORT_SYMBOL(zgid);
|
||||
|
||||
static const struct ib_gid_attr zattr;
|
||||
|
||||
enum gid_attr_find_mask {
|
||||
GID_ATTR_FIND_MASK_GID = 1UL << 0,
|
||||
GID_ATTR_FIND_MASK_NETDEV = 1UL << 1,
|
||||
@@ -76,15 +74,6 @@ enum gid_table_entry_props {
|
||||
GID_TABLE_ENTRY_DEFAULT = 1UL << 1,
|
||||
};
|
||||
|
||||
enum gid_table_write_action {
|
||||
GID_TABLE_WRITE_ACTION_ADD,
|
||||
GID_TABLE_WRITE_ACTION_DEL,
|
||||
/* MODIFY only updates the GID table. Currently only used by
|
||||
* ib_cache_update.
|
||||
*/
|
||||
GID_TABLE_WRITE_ACTION_MODIFY
|
||||
};
|
||||
|
||||
struct ib_gid_table_entry {
|
||||
unsigned long props;
|
||||
union ib_gid gid;
|
||||
@@ -103,31 +92,26 @@ struct ib_gid_table {
|
||||
* (a) Find the GID
|
||||
* (b) Delete it.
|
||||
*
|
||||
* Add/delete should be carried out atomically.
|
||||
* This is done by locking this mutex from multiple
|
||||
* writers. We don't need this lock for IB, as the MAD
|
||||
* layer replaces all entries. All data_vec entries
|
||||
* are locked by this lock.
|
||||
**/
|
||||
struct mutex lock;
|
||||
/* This lock protects the table entries from being
|
||||
* read and written simultaneously.
|
||||
/* Any writer to data_vec must hold this lock and the write side of
|
||||
* rwlock. readers must hold only rwlock. All writers must be in a
|
||||
* sleepable context.
|
||||
*/
|
||||
struct mutex lock;
|
||||
/* rwlock protects data_vec[ix]->props. */
|
||||
rwlock_t rwlock;
|
||||
struct ib_gid_table_entry *data_vec;
|
||||
};
|
||||
|
||||
static void dispatch_gid_change_event(struct ib_device *ib_dev, u8 port)
|
||||
{
|
||||
if (rdma_cap_roce_gid_table(ib_dev, port)) {
|
||||
struct ib_event event;
|
||||
struct ib_event event;
|
||||
|
||||
event.device = ib_dev;
|
||||
event.element.port_num = port;
|
||||
event.event = IB_EVENT_GID_CHANGE;
|
||||
event.device = ib_dev;
|
||||
event.element.port_num = port;
|
||||
event.event = IB_EVENT_GID_CHANGE;
|
||||
|
||||
ib_dispatch_event(&event);
|
||||
}
|
||||
ib_dispatch_event(&event);
|
||||
}
|
||||
|
||||
static const char * const gid_type_str[] = {
|
||||
@@ -168,94 +152,127 @@ int ib_cache_gid_parse_type_str(const char *buf)
|
||||
}
|
||||
EXPORT_SYMBOL(ib_cache_gid_parse_type_str);
|
||||
|
||||
/* This function expects that rwlock will be write locked in all
|
||||
* scenarios and that lock will be locked in sleep-able (RoCE)
|
||||
* scenarios.
|
||||
*/
|
||||
static int write_gid(struct ib_device *ib_dev, u8 port,
|
||||
struct ib_gid_table *table, int ix,
|
||||
const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
enum gid_table_write_action action,
|
||||
bool default_gid)
|
||||
__releases(&table->rwlock) __acquires(&table->rwlock)
|
||||
static void del_roce_gid(struct ib_device *device, u8 port_num,
|
||||
struct ib_gid_table *table, int ix)
|
||||
{
|
||||
pr_debug("%s device=%s port=%d index=%d gid %pI6\n", __func__,
|
||||
device->name, port_num, ix,
|
||||
table->data_vec[ix].gid.raw);
|
||||
|
||||
if (rdma_cap_roce_gid_table(device, port_num))
|
||||
device->del_gid(&table->data_vec[ix].attr,
|
||||
&table->data_vec[ix].context);
|
||||
dev_put(table->data_vec[ix].attr.ndev);
|
||||
}
|
||||
|
||||
static int add_roce_gid(struct ib_gid_table *table,
|
||||
const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr)
|
||||
{
|
||||
struct ib_gid_table_entry *entry;
|
||||
int ix = attr->index;
|
||||
int ret = 0;
|
||||
if_t old_net_dev;
|
||||
enum ib_gid_type old_gid_type;
|
||||
|
||||
/* in rdma_cap_roce_gid_table, this funciton should be protected by a
|
||||
* sleep-able lock.
|
||||
*/
|
||||
|
||||
if (rdma_cap_roce_gid_table(ib_dev, port)) {
|
||||
table->data_vec[ix].props |= GID_TABLE_ENTRY_INVALID;
|
||||
write_unlock_irq(&table->rwlock);
|
||||
/* GID_TABLE_WRITE_ACTION_MODIFY currently isn't supported by
|
||||
* RoCE providers and thus only updates the cache.
|
||||
*/
|
||||
if (action == GID_TABLE_WRITE_ACTION_ADD)
|
||||
ret = ib_dev->add_gid(ib_dev, port, ix, gid, attr,
|
||||
&table->data_vec[ix].context);
|
||||
else if (action == GID_TABLE_WRITE_ACTION_DEL)
|
||||
ret = ib_dev->del_gid(ib_dev, port, ix,
|
||||
&table->data_vec[ix].context);
|
||||
write_lock_irq(&table->rwlock);
|
||||
if (!attr->ndev) {
|
||||
pr_err("%s NULL netdev device=%s port=%d index=%d\n",
|
||||
__func__, attr->device->name, attr->port_num,
|
||||
attr->index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
old_net_dev = table->data_vec[ix].attr.ndev;
|
||||
old_gid_type = table->data_vec[ix].attr.gid_type;
|
||||
if (old_net_dev && old_net_dev != attr->ndev)
|
||||
dev_put(old_net_dev);
|
||||
/* if modify_gid failed, just delete the old gid */
|
||||
if (ret || action == GID_TABLE_WRITE_ACTION_DEL) {
|
||||
gid = &zgid;
|
||||
attr = &zattr;
|
||||
table->data_vec[ix].context = NULL;
|
||||
entry = &table->data_vec[ix];
|
||||
if ((entry->props & GID_TABLE_ENTRY_INVALID) == 0) {
|
||||
WARN(1, "GID table corruption device=%s port=%d index=%d\n",
|
||||
attr->device->name, attr->port_num,
|
||||
attr->index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(&table->data_vec[ix].gid, gid, sizeof(*gid));
|
||||
memcpy(&table->data_vec[ix].attr, attr, sizeof(*attr));
|
||||
if (default_gid) {
|
||||
table->data_vec[ix].props |= GID_TABLE_ENTRY_DEFAULT;
|
||||
if (action == GID_TABLE_WRITE_ACTION_DEL)
|
||||
table->data_vec[ix].attr.gid_type = old_gid_type;
|
||||
if (rdma_cap_roce_gid_table(attr->device, attr->port_num)) {
|
||||
ret = attr->device->add_gid(gid, attr, &entry->context);
|
||||
if (ret) {
|
||||
pr_err("%s GID add failed device=%s port=%d index=%d\n",
|
||||
__func__, attr->device->name, attr->port_num,
|
||||
attr->index);
|
||||
goto add_err;
|
||||
}
|
||||
}
|
||||
if (table->data_vec[ix].attr.ndev &&
|
||||
table->data_vec[ix].attr.ndev != old_net_dev)
|
||||
dev_hold(table->data_vec[ix].attr.ndev);
|
||||
|
||||
table->data_vec[ix].props &= ~GID_TABLE_ENTRY_INVALID;
|
||||
dev_hold(attr->ndev);
|
||||
|
||||
add_err:
|
||||
if (!ret)
|
||||
pr_debug("%s device=%s port=%d index=%d gid %pI6\n", __func__,
|
||||
attr->device->name, attr->port_num, ix, gid->raw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int add_gid(struct ib_device *ib_dev, u8 port,
|
||||
struct ib_gid_table *table, int ix,
|
||||
const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
bool default_gid) {
|
||||
return write_gid(ib_dev, port, table, ix, gid, attr,
|
||||
GID_TABLE_WRITE_ACTION_ADD, default_gid);
|
||||
/**
|
||||
* add_modify_gid - Add or modify GID table entry
|
||||
*
|
||||
* @table: GID table in which GID to be added or modified
|
||||
* @gid: GID content
|
||||
* @attr: Attributes of the GID
|
||||
*
|
||||
* Returns 0 on success or appropriate error code. It accepts zero
|
||||
* GID addition for non RoCE ports for HCA's who report them as valid
|
||||
* GID. However such zero GIDs are not added to the cache.
|
||||
*/
|
||||
static int add_modify_gid(struct ib_gid_table *table,
|
||||
const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (rdma_protocol_roce(attr->device, attr->port_num)) {
|
||||
ret = add_roce_gid(table, gid, attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/*
|
||||
* Some HCA's report multiple GID entries with only one
|
||||
* valid GID, but remaining as zero GID.
|
||||
* So ignore such behavior for IB link layer and don't
|
||||
* fail the call, but don't add such entry to GID cache.
|
||||
*/
|
||||
if (!memcmp(gid, &zgid, sizeof(*gid)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
lockdep_assert_held(&table->lock);
|
||||
memcpy(&table->data_vec[attr->index].gid, gid, sizeof(*gid));
|
||||
memcpy(&table->data_vec[attr->index].attr, attr, sizeof(*attr));
|
||||
|
||||
write_lock_irq(&table->rwlock);
|
||||
table->data_vec[attr->index].props &= ~GID_TABLE_ENTRY_INVALID;
|
||||
write_unlock_irq(&table->rwlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int modify_gid(struct ib_device *ib_dev, u8 port,
|
||||
struct ib_gid_table *table, int ix,
|
||||
const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
bool default_gid) {
|
||||
return write_gid(ib_dev, port, table, ix, gid, attr,
|
||||
GID_TABLE_WRITE_ACTION_MODIFY, default_gid);
|
||||
/**
|
||||
* del_gid - Delete GID table entry
|
||||
*
|
||||
* @ib_dev: IB device whose GID entry to be deleted
|
||||
* @port: Port number of the IB device
|
||||
* @table: GID table of the IB device for a port
|
||||
* @ix: GID entry index to delete
|
||||
*
|
||||
*/
|
||||
static void del_gid(struct ib_device *ib_dev, u8 port,
|
||||
struct ib_gid_table *table, int ix)
|
||||
{
|
||||
lockdep_assert_held(&table->lock);
|
||||
write_lock_irq(&table->rwlock);
|
||||
table->data_vec[ix].props |= GID_TABLE_ENTRY_INVALID;
|
||||
write_unlock_irq(&table->rwlock);
|
||||
|
||||
if (rdma_protocol_roce(ib_dev, port))
|
||||
del_roce_gid(ib_dev, port, table, ix);
|
||||
memcpy(&table->data_vec[ix].gid, &zgid, sizeof(zgid));
|
||||
memset(&table->data_vec[ix].attr, 0, sizeof(table->data_vec[ix].attr));
|
||||
table->data_vec[ix].context = NULL;
|
||||
}
|
||||
|
||||
static int del_gid(struct ib_device *ib_dev, u8 port,
|
||||
struct ib_gid_table *table, int ix,
|
||||
bool default_gid) {
|
||||
return write_gid(ib_dev, port, table, ix, &zgid, &zattr,
|
||||
GID_TABLE_WRITE_ACTION_DEL, default_gid);
|
||||
}
|
||||
|
||||
/* rwlock should be read locked */
|
||||
/* rwlock should be read locked, or lock should be held */
|
||||
static int find_gid(struct ib_gid_table *table, const union ib_gid *gid,
|
||||
const struct ib_gid_attr *val, bool default_gid,
|
||||
unsigned long mask, int *pempty)
|
||||
@@ -271,15 +288,36 @@ static int find_gid(struct ib_gid_table *table, const union ib_gid *gid,
|
||||
|
||||
i++;
|
||||
|
||||
/* find_gid() is used during GID addition where it is expected
|
||||
* to return a free entry slot which is not duplicate.
|
||||
* Free entry slot is requested and returned if pempty is set,
|
||||
* so lookup free slot only if requested.
|
||||
*/
|
||||
if (pempty && empty < 0) {
|
||||
if (data->props & GID_TABLE_ENTRY_INVALID &&
|
||||
(default_gid ==
|
||||
!!(data->props & GID_TABLE_ENTRY_DEFAULT))) {
|
||||
/*
|
||||
* Found an invalid (free) entry; allocate it.
|
||||
* If default GID is requested, then our
|
||||
* found slot must be one of the DEFAULT
|
||||
* reserved slots or we fail.
|
||||
* This ensures that only DEFAULT reserved
|
||||
* slots are used for default property GIDs.
|
||||
*/
|
||||
empty = curr_index;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Additionally find_gid() is used to find valid entry during
|
||||
* lookup operation, where validity needs to be checked. So
|
||||
* find the empty entry first to continue to search for a free
|
||||
* slot and ignore its INVALID flag.
|
||||
*/
|
||||
if (data->props & GID_TABLE_ENTRY_INVALID)
|
||||
continue;
|
||||
|
||||
if (empty < 0)
|
||||
if (!memcmp(&data->gid, &zgid, sizeof(*gid)) &&
|
||||
!memcmp(attr, &zattr, sizeof(*attr)) &&
|
||||
!data->props)
|
||||
empty = curr_index;
|
||||
|
||||
if (found >= 0)
|
||||
continue;
|
||||
|
||||
@@ -329,25 +367,27 @@ static void make_default_gid(if_t dev, union ib_gid *gid)
|
||||
addrconf_ifid_eui48(&gid->raw[8], dev);
|
||||
}
|
||||
|
||||
int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
|
||||
union ib_gid *gid, struct ib_gid_attr *attr)
|
||||
static int __ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
|
||||
union ib_gid *gid, struct ib_gid_attr *attr,
|
||||
unsigned long mask, bool default_gid)
|
||||
{
|
||||
struct ib_gid_table *table;
|
||||
int ix;
|
||||
int ret = 0;
|
||||
int empty;
|
||||
int ix;
|
||||
|
||||
table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;
|
||||
|
||||
/* Do not allow adding zero GID in support of
|
||||
* IB spec version 1.3 section 4.1.1 point (6) and
|
||||
* section 12.7.10 and section 12.7.20
|
||||
*/
|
||||
if (!memcmp(gid, &zgid, sizeof(*gid)))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&table->lock);
|
||||
write_lock_irq(&table->rwlock);
|
||||
table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;
|
||||
|
||||
ix = find_gid(table, gid, attr, false, GID_ATTR_FIND_MASK_GID |
|
||||
GID_ATTR_FIND_MASK_GID_TYPE |
|
||||
GID_ATTR_FIND_MASK_NETDEV, &empty);
|
||||
mutex_lock(&table->lock);
|
||||
|
||||
ix = find_gid(table, gid, attr, default_gid, mask, &empty);
|
||||
if (ix >= 0)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -355,44 +395,74 @@ int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
|
||||
ret = -ENOSPC;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = add_gid(ib_dev, port, table, empty, gid, attr, false);
|
||||
attr->device = ib_dev;
|
||||
attr->index = empty;
|
||||
attr->port_num = port;
|
||||
ret = add_modify_gid(table, gid, attr);
|
||||
if (!ret)
|
||||
dispatch_gid_change_event(ib_dev, port);
|
||||
|
||||
out_unlock:
|
||||
write_unlock_irq(&table->rwlock);
|
||||
mutex_unlock(&table->lock);
|
||||
if (ret)
|
||||
pr_warn("%s: unable to add gid %pI6 error=%d\n",
|
||||
__func__, gid->raw, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
|
||||
union ib_gid *gid, struct ib_gid_attr *attr)
|
||||
{
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
|
||||
mask = GID_ATTR_FIND_MASK_GID |
|
||||
GID_ATTR_FIND_MASK_GID_TYPE |
|
||||
GID_ATTR_FIND_MASK_NETDEV;
|
||||
|
||||
ret = __ib_cache_gid_add(ib_dev, port, gid, attr, mask, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
_ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
|
||||
union ib_gid *gid, struct ib_gid_attr *attr,
|
||||
unsigned long mask, bool default_gid)
|
||||
{
|
||||
struct ib_gid_table *table;
|
||||
int ret = 0;
|
||||
int ix;
|
||||
|
||||
table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;
|
||||
|
||||
mutex_lock(&table->lock);
|
||||
|
||||
ix = find_gid(table, gid, attr, default_gid, mask, NULL);
|
||||
if (ix < 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
del_gid(ib_dev, port, table, ix);
|
||||
dispatch_gid_change_event(ib_dev, port);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&table->lock);
|
||||
if (ret)
|
||||
pr_debug("%s: can't delete gid %pI6 error=%d\n",
|
||||
__func__, gid->raw, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
|
||||
union ib_gid *gid, struct ib_gid_attr *attr)
|
||||
{
|
||||
struct ib_gid_table *table;
|
||||
int ix;
|
||||
unsigned long mask = GID_ATTR_FIND_MASK_GID |
|
||||
GID_ATTR_FIND_MASK_GID_TYPE |
|
||||
GID_ATTR_FIND_MASK_DEFAULT |
|
||||
GID_ATTR_FIND_MASK_NETDEV;
|
||||
|
||||
table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;
|
||||
|
||||
mutex_lock(&table->lock);
|
||||
write_lock_irq(&table->rwlock);
|
||||
|
||||
ix = find_gid(table, gid, attr, false,
|
||||
GID_ATTR_FIND_MASK_GID |
|
||||
GID_ATTR_FIND_MASK_GID_TYPE |
|
||||
GID_ATTR_FIND_MASK_NETDEV |
|
||||
GID_ATTR_FIND_MASK_DEFAULT,
|
||||
NULL);
|
||||
if (ix < 0)
|
||||
goto out_unlock;
|
||||
|
||||
if (!del_gid(ib_dev, port, table, ix, false))
|
||||
dispatch_gid_change_event(ib_dev, port);
|
||||
|
||||
out_unlock:
|
||||
write_unlock_irq(&table->rwlock);
|
||||
mutex_unlock(&table->lock);
|
||||
return 0;
|
||||
return _ib_cache_gid_del(ib_dev, port, gid, attr, mask, false);
|
||||
}
|
||||
|
||||
int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
|
||||
@@ -405,16 +475,14 @@ int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
|
||||
table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;
|
||||
|
||||
mutex_lock(&table->lock);
|
||||
write_lock_irq(&table->rwlock);
|
||||
|
||||
for (ix = 0; ix < table->sz; ix++)
|
||||
if (table->data_vec[ix].attr.ndev == ndev)
|
||||
if (!del_gid(ib_dev, port, table, ix,
|
||||
!!(table->data_vec[ix].props &
|
||||
GID_TABLE_ENTRY_DEFAULT)))
|
||||
deleted = true;
|
||||
for (ix = 0; ix < table->sz; ix++) {
|
||||
if (table->data_vec[ix].attr.ndev == ndev) {
|
||||
del_gid(ib_dev, port, table, ix);
|
||||
deleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
write_unlock_irq(&table->rwlock);
|
||||
mutex_unlock(&table->lock);
|
||||
|
||||
if (deleted)
|
||||
@@ -497,6 +565,19 @@ static int ib_cache_gid_find(struct ib_device *ib_dev,
|
||||
mask, port, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_find_cached_gid_by_port - Returns the GID table index where a specified
|
||||
* GID value occurs. It searches for the specified GID value in the local
|
||||
* software cache.
|
||||
* @device: The device to query.
|
||||
* @gid: The GID value to search for.
|
||||
* @gid_type: The GID type to search for.
|
||||
* @port_num: The port number of the device where the GID value should be
|
||||
* searched.
|
||||
* @ndev: In RoCE, the net device of the device. Null means ignore.
|
||||
* @index: The index into the cached GID table where the GID was found. This
|
||||
* parameter may be NULL.
|
||||
*/
|
||||
int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
@@ -533,7 +614,7 @@ int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
|
||||
EXPORT_SYMBOL(ib_find_cached_gid_by_port);
|
||||
|
||||
/**
|
||||
* ib_find_gid_by_filter - Returns the GID table index where a specified
|
||||
* ib_cache_gid_find_by_filter - Returns the GID table index where a specified
|
||||
* GID value occurs
|
||||
* @device: The device to query.
|
||||
* @gid: The GID value to search for.
|
||||
@@ -544,7 +625,7 @@ EXPORT_SYMBOL(ib_find_cached_gid_by_port);
|
||||
* otherwise, we continue searching the GID table. It's guaranteed that
|
||||
* while filter is executed, ndev field is valid and the structure won't
|
||||
* change. filter is executed in an atomic context. filter must not be NULL.
|
||||
* @index: The index into the cached GID table where the GID was found. This
|
||||
* @index: The index into the cached GID table where the GID was found. This
|
||||
* parameter may be NULL.
|
||||
*
|
||||
* ib_cache_gid_find_by_filter() searches for the specified GID value
|
||||
@@ -604,6 +685,7 @@ static struct ib_gid_table *alloc_gid_table(int sz)
|
||||
{
|
||||
struct ib_gid_table *table =
|
||||
kzalloc(sizeof(struct ib_gid_table), GFP_KERNEL);
|
||||
int i;
|
||||
|
||||
if (!table)
|
||||
return NULL;
|
||||
@@ -617,6 +699,11 @@ static struct ib_gid_table *alloc_gid_table(int sz)
|
||||
table->sz = sz;
|
||||
rwlock_init(&table->rwlock);
|
||||
|
||||
/* Mark all entries as invalid so that allocator can allocate
|
||||
* one of the invalid (free) entry.
|
||||
*/
|
||||
for (i = 0; i < sz; i++)
|
||||
table->data_vec[i].props |= GID_TABLE_ENTRY_INVALID;
|
||||
return table;
|
||||
|
||||
err_free_table:
|
||||
@@ -641,16 +728,15 @@ static void cleanup_gid_table_port(struct ib_device *ib_dev, u8 port,
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
write_lock_irq(&table->rwlock);
|
||||
mutex_lock(&table->lock);
|
||||
for (i = 0; i < table->sz; ++i) {
|
||||
if (memcmp(&table->data_vec[i].gid, &zgid,
|
||||
sizeof(table->data_vec[i].gid)))
|
||||
if (!del_gid(ib_dev, port, table, i,
|
||||
table->data_vec[i].props &
|
||||
GID_ATTR_FIND_MASK_DEFAULT))
|
||||
deleted = true;
|
||||
sizeof(table->data_vec[i].gid))) {
|
||||
del_gid(ib_dev, port, table, i);
|
||||
deleted = true;
|
||||
}
|
||||
}
|
||||
write_unlock_irq(&table->rwlock);
|
||||
mutex_unlock(&table->lock);
|
||||
|
||||
if (deleted)
|
||||
dispatch_gid_change_event(ib_dev, port);
|
||||
@@ -661,15 +747,17 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
|
||||
unsigned long gid_type_mask,
|
||||
enum ib_cache_gid_default_mode mode)
|
||||
{
|
||||
union ib_gid gid;
|
||||
union ib_gid gid = { };
|
||||
struct ib_gid_attr gid_attr;
|
||||
struct ib_gid_attr zattr_type = zattr;
|
||||
struct ib_gid_table *table;
|
||||
unsigned int gid_type;
|
||||
unsigned long mask;
|
||||
|
||||
table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;
|
||||
|
||||
make_default_gid(ndev, &gid);
|
||||
mask = GID_ATTR_FIND_MASK_GID_TYPE |
|
||||
GID_ATTR_FIND_MASK_DEFAULT |
|
||||
GID_ATTR_FIND_MASK_NETDEV;
|
||||
memset(&gid_attr, 0, sizeof(gid_attr));
|
||||
gid_attr.ndev = ndev;
|
||||
|
||||
@@ -684,60 +772,19 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
|
||||
#endif
|
||||
|
||||
for (gid_type = 0; gid_type < IB_GID_TYPE_SIZE; ++gid_type) {
|
||||
int ix;
|
||||
union ib_gid current_gid;
|
||||
struct ib_gid_attr current_gid_attr = {};
|
||||
|
||||
if (1UL << gid_type & ~gid_type_mask)
|
||||
continue;
|
||||
|
||||
gid_attr.gid_type = gid_type;
|
||||
|
||||
mutex_lock(&table->lock);
|
||||
write_lock_irq(&table->rwlock);
|
||||
ix = find_gid(table, NULL, &gid_attr, true,
|
||||
GID_ATTR_FIND_MASK_GID_TYPE |
|
||||
GID_ATTR_FIND_MASK_DEFAULT,
|
||||
NULL);
|
||||
|
||||
/* Coudn't find default GID location */
|
||||
if (WARN_ON(ix < 0))
|
||||
goto release;
|
||||
|
||||
zattr_type.gid_type = gid_type;
|
||||
|
||||
if (!__ib_cache_gid_get(ib_dev, port, ix,
|
||||
¤t_gid, ¤t_gid_attr) &&
|
||||
mode == IB_CACHE_GID_DEFAULT_MODE_SET &&
|
||||
!memcmp(&gid, ¤t_gid, sizeof(gid)) &&
|
||||
!memcmp(&gid_attr, ¤t_gid_attr, sizeof(gid_attr)))
|
||||
goto release;
|
||||
|
||||
if (memcmp(¤t_gid, &zgid, sizeof(current_gid)) ||
|
||||
memcmp(¤t_gid_attr, &zattr_type,
|
||||
sizeof(current_gid_attr))) {
|
||||
if (del_gid(ib_dev, port, table, ix, true)) {
|
||||
pr_warn("ib_cache_gid: can't delete index %d for default gid %pI6\n",
|
||||
ix, gid.raw);
|
||||
goto release;
|
||||
} else {
|
||||
dispatch_gid_change_event(ib_dev, port);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) {
|
||||
if (add_gid(ib_dev, port, table, ix, &gid, &gid_attr, true))
|
||||
pr_warn("ib_cache_gid: unable to add default gid %pI6\n",
|
||||
gid.raw);
|
||||
else
|
||||
dispatch_gid_change_event(ib_dev, port);
|
||||
make_default_gid(ndev, &gid);
|
||||
__ib_cache_gid_add(ib_dev, port, &gid,
|
||||
&gid_attr, mask, true);
|
||||
} else if (mode == IB_CACHE_GID_DEFAULT_MODE_DELETE) {
|
||||
_ib_cache_gid_del(ib_dev, port, &gid,
|
||||
&gid_attr, mask, true);
|
||||
}
|
||||
|
||||
release:
|
||||
if (current_gid_attr.ndev)
|
||||
dev_put(current_gid_attr.ndev);
|
||||
write_unlock_irq(&table->rwlock);
|
||||
mutex_unlock(&table->lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,6 +916,20 @@ int ib_get_cached_gid(struct ib_device *device,
|
||||
}
|
||||
EXPORT_SYMBOL(ib_get_cached_gid);
|
||||
|
||||
/**
|
||||
* ib_find_cached_gid - Returns the port number and GID table index where
|
||||
* a specified GID value occurs.
|
||||
* @device: The device to query.
|
||||
* @gid: The GID value to search for.
|
||||
* @gid_type: The GID type to search for.
|
||||
* @ndev: In RoCE, the net device of the device. NULL means ignore.
|
||||
* @port_num: The port number of the device where the GID value was found.
|
||||
* @index: The index into the cached GID table where the GID was found. This
|
||||
* parameter may be NULL.
|
||||
*
|
||||
* ib_find_cached_gid() searches for the specified GID value in
|
||||
* the local software cache.
|
||||
*/
|
||||
int ib_find_cached_gid(struct ib_device *device,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
@@ -889,7 +950,7 @@ int ib_find_gid_by_filter(struct ib_device *device,
|
||||
void *context, u16 *index)
|
||||
{
|
||||
/* Only RoCE GID table supports filter function */
|
||||
if (!rdma_cap_roce_gid_table(device, port_num) && filter)
|
||||
if (!rdma_protocol_roce(device, port_num) && filter)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
return ib_cache_gid_find_by_filter(device, gid,
|
||||
@@ -1034,20 +1095,45 @@ int ib_get_cached_port_state(struct ib_device *device,
|
||||
}
|
||||
EXPORT_SYMBOL(ib_get_cached_port_state);
|
||||
|
||||
static int config_non_roce_gid_cache(struct ib_device *device,
|
||||
u8 port, int gid_tbl_len)
|
||||
{
|
||||
struct ib_gid_attr gid_attr = {};
|
||||
struct ib_gid_table *table;
|
||||
union ib_gid gid;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
gid_attr.device = device;
|
||||
gid_attr.port_num = port;
|
||||
table = device->cache.ports[port - rdma_start_port(device)].gid;
|
||||
|
||||
mutex_lock(&table->lock);
|
||||
for (i = 0; i < gid_tbl_len; ++i) {
|
||||
if (!device->query_gid)
|
||||
continue;
|
||||
ret = device->query_gid(device, port, i, &gid);
|
||||
if (ret) {
|
||||
pr_warn("query_gid failed (%d) for %s (index %d)\n",
|
||||
ret, device->name, i);
|
||||
goto err;
|
||||
}
|
||||
gid_attr.index = i;
|
||||
add_modify_gid(table, &gid, &gid_attr);
|
||||
}
|
||||
err:
|
||||
mutex_unlock(&table->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ib_cache_update(struct ib_device *device,
|
||||
u8 port)
|
||||
{
|
||||
struct ib_port_attr *tprops = NULL;
|
||||
struct ib_pkey_cache *pkey_cache = NULL, *old_pkey_cache;
|
||||
struct ib_gid_cache {
|
||||
int table_len;
|
||||
union ib_gid table[0];
|
||||
} *gid_cache = NULL;
|
||||
int i;
|
||||
int ret;
|
||||
struct ib_gid_table *table;
|
||||
bool use_roce_gid_table =
|
||||
rdma_cap_roce_gid_table(device, port);
|
||||
|
||||
if (!rdma_is_port_valid(device, port))
|
||||
return;
|
||||
@@ -1065,6 +1151,13 @@ static void ib_cache_update(struct ib_device *device,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!rdma_protocol_roce(device, port)) {
|
||||
ret = config_non_roce_gid_cache(device, port,
|
||||
tprops->gid_tbl_len);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkey_cache = kmalloc(sizeof *pkey_cache + tprops->pkey_tbl_len *
|
||||
sizeof *pkey_cache->table, GFP_KERNEL);
|
||||
if (!pkey_cache)
|
||||
@@ -1072,15 +1165,6 @@ static void ib_cache_update(struct ib_device *device,
|
||||
|
||||
pkey_cache->table_len = tprops->pkey_tbl_len;
|
||||
|
||||
if (!use_roce_gid_table) {
|
||||
gid_cache = kmalloc(sizeof(*gid_cache) + tprops->gid_tbl_len *
|
||||
sizeof(*gid_cache->table), GFP_KERNEL);
|
||||
if (!gid_cache)
|
||||
goto err;
|
||||
|
||||
gid_cache->table_len = tprops->gid_tbl_len;
|
||||
}
|
||||
|
||||
for (i = 0; i < pkey_cache->table_len; ++i) {
|
||||
ret = ib_query_pkey(device, port, i, pkey_cache->table + i);
|
||||
if (ret) {
|
||||
@@ -1090,47 +1174,24 @@ static void ib_cache_update(struct ib_device *device,
|
||||
}
|
||||
}
|
||||
|
||||
if (!use_roce_gid_table) {
|
||||
for (i = 0; i < gid_cache->table_len; ++i) {
|
||||
ret = ib_query_gid(device, port, i,
|
||||
gid_cache->table + i, NULL);
|
||||
if (ret) {
|
||||
pr_warn("ib_query_gid failed (%d) for %s (index %d)\n",
|
||||
ret, device->name, i);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_lock_irq(&device->cache.lock);
|
||||
|
||||
old_pkey_cache = device->cache.ports[port -
|
||||
rdma_start_port(device)].pkey;
|
||||
|
||||
device->cache.ports[port - rdma_start_port(device)].pkey = pkey_cache;
|
||||
if (!use_roce_gid_table) {
|
||||
write_lock(&table->rwlock);
|
||||
for (i = 0; i < gid_cache->table_len; i++) {
|
||||
modify_gid(device, port, table, i, gid_cache->table + i,
|
||||
&zattr, false);
|
||||
}
|
||||
write_unlock(&table->rwlock);
|
||||
}
|
||||
|
||||
device->cache.ports[port - rdma_start_port(device)].lmc = tprops->lmc;
|
||||
device->cache.ports[port - rdma_start_port(device)].port_state =
|
||||
tprops->state;
|
||||
|
||||
write_unlock_irq(&device->cache.lock);
|
||||
|
||||
kfree(gid_cache);
|
||||
kfree(old_pkey_cache);
|
||||
kfree(tprops);
|
||||
return;
|
||||
|
||||
err:
|
||||
kfree(pkey_cache);
|
||||
kfree(gid_cache);
|
||||
kfree(tprops);
|
||||
}
|
||||
|
||||
|
||||
@@ -494,13 +494,31 @@ static int cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
|
||||
grh, &av->ah_attr);
|
||||
}
|
||||
|
||||
static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
|
||||
struct cm_id_private *cm_id_priv)
|
||||
static int add_cm_id_to_port_list(struct cm_id_private *cm_id_priv,
|
||||
struct cm_av *av,
|
||||
struct cm_port *port)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&cm.lock, flags);
|
||||
|
||||
if (&cm_id_priv->av == av)
|
||||
list_add_tail(&cm_id_priv->prim_list, &port->cm_priv_prim_list);
|
||||
else if (&cm_id_priv->alt_av == av)
|
||||
list_add_tail(&cm_id_priv->altr_list, &port->cm_priv_altr_list);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
spin_unlock_irqrestore(&cm.lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cm_port *get_cm_port_from_path(struct sa_path_rec *path)
|
||||
{
|
||||
struct cm_device *cm_dev;
|
||||
struct cm_port *port = NULL;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
u8 p;
|
||||
if_t ndev = ib_get_ndev_from_path(path);
|
||||
|
||||
@@ -509,7 +527,7 @@ static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
|
||||
if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
|
||||
sa_conv_pathrec_to_gid_type(path),
|
||||
ndev, &p, NULL)) {
|
||||
port = cm_dev->port[p-1];
|
||||
port = cm_dev->port[p - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -517,9 +535,20 @@ static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
|
||||
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
return port;
|
||||
}
|
||||
|
||||
static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
|
||||
struct cm_id_private *cm_id_priv)
|
||||
{
|
||||
struct cm_device *cm_dev;
|
||||
struct cm_port *port;
|
||||
int ret;
|
||||
|
||||
port = get_cm_port_from_path(path);
|
||||
if (!port)
|
||||
return -EINVAL;
|
||||
cm_dev = port->cm_dev;
|
||||
|
||||
ret = ib_find_cached_pkey(cm_dev->ib_device, port->port_num,
|
||||
be16_to_cpu(path->pkey), &av->pkey_index);
|
||||
@@ -534,16 +563,7 @@ static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
|
||||
|
||||
av->timeout = path->packet_life_time + 1;
|
||||
|
||||
spin_lock_irqsave(&cm.lock, flags);
|
||||
if (&cm_id_priv->av == av)
|
||||
list_add_tail(&cm_id_priv->prim_list, &port->cm_priv_prim_list);
|
||||
else if (&cm_id_priv->alt_av == av)
|
||||
list_add_tail(&cm_id_priv->altr_list, &port->cm_priv_altr_list);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
spin_unlock_irqrestore(&cm.lock, flags);
|
||||
|
||||
ret = add_cm_id_to_port_list(cm_id_priv, av, port);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1548,6 +1568,8 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
|
||||
cm_req_get_primary_local_ack_timeout(req_msg);
|
||||
primary_path->packet_life_time -= (primary_path->packet_life_time > 0);
|
||||
primary_path->service_id = req_msg->service_id;
|
||||
if (sa_path_is_roce(primary_path))
|
||||
primary_path->roce.route_resolved = false;
|
||||
|
||||
if (cm_req_has_alt_path(req_msg)) {
|
||||
alt_path->dgid = req_msg->alt_local_gid;
|
||||
@@ -1567,6 +1589,9 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
|
||||
cm_req_get_alt_local_ack_timeout(req_msg);
|
||||
alt_path->packet_life_time -= (alt_path->packet_life_time > 0);
|
||||
alt_path->service_id = req_msg->service_id;
|
||||
|
||||
if (sa_path_is_roce(alt_path))
|
||||
alt_path->roce.route_resolved = false;
|
||||
}
|
||||
cm_format_path_lid_from_req(req_msg, primary_path, alt_path);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include <sys/priv.h>
|
||||
|
||||
#include "core_priv.h"
|
||||
#include "cma_priv.h"
|
||||
|
||||
MODULE_AUTHOR("Sean Hefty");
|
||||
MODULE_DESCRIPTION("Generic RDMA CM Agent");
|
||||
@@ -168,7 +169,6 @@ static struct ib_client cma_client = {
|
||||
};
|
||||
|
||||
static struct ib_sa_client sa_client;
|
||||
static struct rdma_addr_client addr_client;
|
||||
static LIST_HEAD(dev_list);
|
||||
static LIST_HEAD(listen_any_list);
|
||||
static DEFINE_MUTEX(lock);
|
||||
@@ -351,49 +351,6 @@ struct ib_device *cma_get_ib_dev(struct cma_device *cma_dev)
|
||||
* We do this by disabling removal notification while a callback is in process,
|
||||
* and reporting it after the callback completes.
|
||||
*/
|
||||
struct rdma_id_private {
|
||||
struct rdma_cm_id id;
|
||||
|
||||
struct rdma_bind_list *bind_list;
|
||||
struct hlist_node node;
|
||||
struct list_head list; /* listen_any_list or cma_device.list */
|
||||
struct list_head listen_list; /* per device listens */
|
||||
struct cma_device *cma_dev;
|
||||
struct list_head mc_list;
|
||||
|
||||
int internal_id;
|
||||
enum rdma_cm_state state;
|
||||
spinlock_t lock;
|
||||
struct mutex qp_mutex;
|
||||
|
||||
struct completion comp;
|
||||
atomic_t refcount;
|
||||
struct mutex handler_mutex;
|
||||
|
||||
int backlog;
|
||||
int timeout_ms;
|
||||
struct ib_sa_query *query;
|
||||
int query_id;
|
||||
union {
|
||||
struct ib_cm_id *ib;
|
||||
struct iw_cm_id *iw;
|
||||
} cm_id;
|
||||
|
||||
u32 seq_num;
|
||||
u32 qkey;
|
||||
u32 qp_num;
|
||||
pid_t owner;
|
||||
u32 options;
|
||||
u8 srq;
|
||||
u8 tos;
|
||||
u8 tos_set:1;
|
||||
u8 timeout_set:1;
|
||||
u8 reuseaddr;
|
||||
u8 afonly;
|
||||
u8 timeout;
|
||||
enum ib_gid_type gid_type;
|
||||
};
|
||||
|
||||
struct cma_multicast {
|
||||
struct rdma_id_private *id_priv;
|
||||
union {
|
||||
@@ -941,7 +898,6 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
|
||||
{
|
||||
struct ib_qp_attr qp_attr;
|
||||
int qp_attr_mask, ret;
|
||||
union ib_gid sgid;
|
||||
|
||||
mutex_lock(&id_priv->qp_mutex);
|
||||
if (!id_priv->id.qp) {
|
||||
@@ -964,12 +920,6 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = ib_query_gid(id_priv->id.device, id_priv->id.port_num,
|
||||
rdma_ah_read_grh(&qp_attr.ah_attr)->sgid_index,
|
||||
&sgid, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
BUG_ON(id_priv->cma_dev->device != id_priv->id.device);
|
||||
|
||||
if (conn_param)
|
||||
@@ -1712,21 +1662,12 @@ static bool cma_match_private_data(struct rdma_id_private *id_priv,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cma_protocol_roce_dev_port(struct ib_device *device, int port_num)
|
||||
{
|
||||
enum rdma_link_layer ll = rdma_port_get_link_layer(device, port_num);
|
||||
enum rdma_transport_type transport =
|
||||
rdma_node_get_transport(device->node_type);
|
||||
|
||||
return ll == IB_LINK_LAYER_ETHERNET && transport == RDMA_TRANSPORT_IB;
|
||||
}
|
||||
|
||||
static bool cma_protocol_roce(const struct rdma_cm_id *id)
|
||||
{
|
||||
struct ib_device *device = id->device;
|
||||
const int port_num = id->port_num ?: rdma_start_port(device);
|
||||
|
||||
return cma_protocol_roce_dev_port(device, port_num);
|
||||
return rdma_protocol_roce(device, port_num);
|
||||
}
|
||||
|
||||
static bool cma_match_net_dev(const struct rdma_cm_id *id,
|
||||
@@ -1746,8 +1687,8 @@ static bool cma_match_net_dev(const struct rdma_cm_id *id,
|
||||
return false;
|
||||
}
|
||||
/* This request is an AF_IB request or a RoCE request */
|
||||
return addr->src_addr.ss_family == AF_IB ||
|
||||
cma_protocol_roce_dev_port(id->device, port_num);
|
||||
return (addr->src_addr.ss_family == AF_IB ||
|
||||
rdma_protocol_roce(id->device, port_num));
|
||||
}
|
||||
|
||||
return !addr->dev_addr.bound_dev_if ||
|
||||
@@ -1808,6 +1749,10 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
|
||||
if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) {
|
||||
/* Assuming the protocol is AF_IB */
|
||||
*net_dev = NULL;
|
||||
} else if (rdma_protocol_roce(req.device, req.port)) {
|
||||
/* TODO find the net dev matching the request parameters
|
||||
* through the RoCE GID table */
|
||||
*net_dev = NULL;
|
||||
} else {
|
||||
return ERR_CAST(*net_dev);
|
||||
}
|
||||
@@ -2840,6 +2785,7 @@ cma_iboe_set_path_rec_l2_fields(struct rdma_id_private *id_priv)
|
||||
gid_type = ib_network_to_gid_type(addr->dev_addr.network);
|
||||
route->path_rec->rec_type = sa_conv_gid_to_pathrec_type(gid_type);
|
||||
|
||||
route->path_rec->roce.route_resolved = true;
|
||||
sa_path_set_ndev(route->path_rec, addr->dev_addr.net);
|
||||
sa_path_set_ifindex(route->path_rec, if_getindex(ndev));
|
||||
sa_path_set_dmac(route->path_rec, addr->dev_addr.dst_dev_addr);
|
||||
@@ -3232,7 +3178,7 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv),
|
||||
ret = rdma_resolve_ip(cma_src_addr(id_priv),
|
||||
dst_addr, &id->route.addr.dev_addr,
|
||||
timeout_ms, addr_handler, id_priv);
|
||||
}
|
||||
@@ -4838,7 +4784,6 @@ static int __init cma_init(void)
|
||||
return -ENOMEM;
|
||||
|
||||
ib_sa_register_client(&sa_client);
|
||||
rdma_addr_register_client(&addr_client);
|
||||
|
||||
ret = ib_register_client(&cma_client);
|
||||
if (ret)
|
||||
@@ -4849,7 +4794,6 @@ static int __init cma_init(void)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
rdma_addr_unregister_client(&addr_client);
|
||||
ib_sa_unregister_client(&sa_client);
|
||||
destroy_workqueue(cma_wq);
|
||||
return ret;
|
||||
@@ -4859,7 +4803,6 @@ static void __exit cma_cleanup(void)
|
||||
{
|
||||
cma_configfs_exit();
|
||||
ib_unregister_client(&cma_client);
|
||||
rdma_addr_unregister_client(&addr_client);
|
||||
ib_sa_unregister_client(&sa_client);
|
||||
destroy_workqueue(cma_wq);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,6 @@ static int ib_device_check_mandatory(struct ib_device *device)
|
||||
IB_MANDATORY_FUNC(query_device),
|
||||
IB_MANDATORY_FUNC(query_port),
|
||||
IB_MANDATORY_FUNC(query_pkey),
|
||||
IB_MANDATORY_FUNC(query_gid),
|
||||
IB_MANDATORY_FUNC(alloc_pd),
|
||||
IB_MANDATORY_FUNC(dealloc_pd),
|
||||
IB_MANDATORY_FUNC(create_ah),
|
||||
@@ -667,7 +666,7 @@ int ib_query_port(struct ib_device *device,
|
||||
if (rdma_port_get_link_layer(device, port_num) != IB_LINK_LAYER_INFINIBAND)
|
||||
return 0;
|
||||
|
||||
err = ib_query_gid(device, port_num, 0, &gid, NULL);
|
||||
err = device->query_gid(device, port_num, 0, &gid);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -685,19 +684,13 @@ EXPORT_SYMBOL(ib_query_port);
|
||||
* @attr: Returned GID attributes related to this GID index (only in RoCE).
|
||||
* NULL means ignore.
|
||||
*
|
||||
* ib_query_gid() fetches the specified GID table entry.
|
||||
* ib_query_gid() fetches the specified GID table entry from the cache.
|
||||
*/
|
||||
int ib_query_gid(struct ib_device *device,
|
||||
u8 port_num, int index, union ib_gid *gid,
|
||||
struct ib_gid_attr *attr)
|
||||
{
|
||||
if (rdma_cap_roce_gid_table(device, port_num))
|
||||
return ib_get_cached_gid(device, port_num, index, gid, attr);
|
||||
|
||||
if (attr)
|
||||
return -EINVAL;
|
||||
|
||||
return device->query_gid(device, port_num, index, gid);
|
||||
return ib_get_cached_gid(device, port_num, index, gid, attr);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_query_gid);
|
||||
|
||||
@@ -860,19 +853,18 @@ EXPORT_SYMBOL(ib_modify_port);
|
||||
* a specified GID value occurs. Its searches only for IB link layer.
|
||||
* @device: The device to query.
|
||||
* @gid: The GID value to search for.
|
||||
* @ndev: The ndev related to the GID to search for.
|
||||
* @port_num: The port number of the device where the GID value was found.
|
||||
* @index: The index into the GID table where the GID was found. This
|
||||
* parameter may be NULL.
|
||||
*/
|
||||
int ib_find_gid(struct ib_device *device, union ib_gid *gid,
|
||||
if_t ndev, u8 *port_num, u16 *index)
|
||||
u8 *port_num, u16 *index)
|
||||
{
|
||||
union ib_gid tmp_gid;
|
||||
int ret, port, i;
|
||||
|
||||
for (port = rdma_start_port(device); port <= rdma_end_port(device); ++port) {
|
||||
if (rdma_cap_roce_gid_table(device, port))
|
||||
if (!rdma_protocol_ib(device, port))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) {
|
||||
|
||||
@@ -790,112 +790,126 @@ static u8 get_src_path_mask(struct ib_device *device, u8 port_num)
|
||||
return src_path_mask;
|
||||
}
|
||||
|
||||
static int
|
||||
roce_resolve_route_from_path(struct ib_device *device, u8 port_num,
|
||||
struct sa_path_rec *rec)
|
||||
{
|
||||
if_t resolved_dev;
|
||||
if_t ndev;
|
||||
if_t idev;
|
||||
struct rdma_dev_addr dev_addr = {
|
||||
.bound_dev_if = ((sa_path_get_ifindex(rec) >= 0) ?
|
||||
sa_path_get_ifindex(rec) : 0),
|
||||
.net = sa_path_get_ndev(rec) ?
|
||||
sa_path_get_ndev(rec) :
|
||||
&init_net
|
||||
};
|
||||
union rdma_sockaddr sgid_addr, dgid_addr;
|
||||
int ret;
|
||||
|
||||
if (rec->roce.route_resolved)
|
||||
return 0;
|
||||
|
||||
if (!device->get_netdev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rdma_gid2ip(&sgid_addr._sockaddr, &rec->sgid);
|
||||
rdma_gid2ip(&dgid_addr._sockaddr, &rec->dgid);
|
||||
|
||||
/* validate the route */
|
||||
ret = rdma_resolve_ip_route(&sgid_addr._sockaddr,
|
||||
&dgid_addr._sockaddr, &dev_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((dev_addr.network == RDMA_NETWORK_IPV4 ||
|
||||
dev_addr.network == RDMA_NETWORK_IPV6) &&
|
||||
rec->rec_type != SA_PATH_REC_TYPE_ROCE_V2)
|
||||
return -EINVAL;
|
||||
|
||||
idev = device->get_netdev(device, port_num);
|
||||
if (!idev)
|
||||
return -ENODEV;
|
||||
|
||||
resolved_dev = dev_get_by_index(dev_addr.net,
|
||||
dev_addr.bound_dev_if);
|
||||
if (!resolved_dev) {
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
ndev = ib_get_ndev_from_path(rec);
|
||||
rcu_read_lock();
|
||||
if ((ndev && ndev != resolved_dev) ||
|
||||
(resolved_dev != idev &&
|
||||
rdma_vlan_dev_real_dev(resolved_dev) != idev))
|
||||
ret = -EHOSTUNREACH;
|
||||
rcu_read_unlock();
|
||||
dev_put(resolved_dev);
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
done:
|
||||
dev_put(idev);
|
||||
if (!ret)
|
||||
rec->roce.route_resolved = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_ah_attr_grh_fields(struct ib_device *device, u8 port_num,
|
||||
struct sa_path_rec *rec,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
enum ib_gid_type type = sa_conv_pathrec_to_gid_type(rec);
|
||||
if_t ndev;
|
||||
u16 gid_index;
|
||||
int ret;
|
||||
|
||||
ndev = ib_get_ndev_from_path(rec);
|
||||
ret = ib_find_cached_gid_by_port(device, &rec->sgid, type,
|
||||
port_num, ndev, &gid_index);
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rdma_ah_set_grh(ah_attr, &rec->dgid,
|
||||
be32_to_cpu(rec->flow_label),
|
||||
gid_index, rec->hop_limit,
|
||||
rec->traffic_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ib_init_ah_attr_from_path(struct ib_device *device, u8 port_num,
|
||||
struct sa_path_rec *rec,
|
||||
struct rdma_ah_attr *ah_attr)
|
||||
{
|
||||
int ret;
|
||||
u16 gid_index;
|
||||
int use_roce;
|
||||
if_t ndev = NULL;
|
||||
int ret = 0;
|
||||
|
||||
memset(ah_attr, 0, sizeof *ah_attr);
|
||||
memset(ah_attr, 0, sizeof(*ah_attr));
|
||||
ah_attr->type = rdma_ah_find_type(device, port_num);
|
||||
|
||||
rdma_ah_set_dlid(ah_attr, be32_to_cpu(sa_path_get_dlid(rec)));
|
||||
|
||||
if ((ah_attr->type == RDMA_AH_ATTR_TYPE_OPA) &&
|
||||
(rdma_ah_get_dlid(ah_attr) == be16_to_cpu(IB_LID_PERMISSIVE)))
|
||||
rdma_ah_set_make_grd(ah_attr, true);
|
||||
|
||||
rdma_ah_set_sl(ah_attr, rec->sl);
|
||||
rdma_ah_set_path_bits(ah_attr, be32_to_cpu(sa_path_get_slid(rec)) &
|
||||
get_src_path_mask(device, port_num));
|
||||
rdma_ah_set_port_num(ah_attr, port_num);
|
||||
rdma_ah_set_static_rate(ah_attr, rec->rate);
|
||||
use_roce = rdma_cap_eth_ah(device, port_num);
|
||||
|
||||
if (use_roce) {
|
||||
if_t idev;
|
||||
if_t resolved_dev;
|
||||
struct rdma_dev_addr dev_addr = {
|
||||
.bound_dev_if = ((sa_path_get_ifindex(rec) >= 0) ?
|
||||
sa_path_get_ifindex(rec) : 0),
|
||||
.net = sa_path_get_ndev(rec) ?
|
||||
sa_path_get_ndev(rec) :
|
||||
&init_net
|
||||
};
|
||||
union rdma_sockaddr sgid_addr, dgid_addr;
|
||||
|
||||
if (!device->get_netdev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rdma_gid2ip(&sgid_addr._sockaddr, &rec->sgid);
|
||||
rdma_gid2ip(&dgid_addr._sockaddr, &rec->dgid);
|
||||
|
||||
/* validate the route */
|
||||
ret = rdma_resolve_ip_route(&sgid_addr._sockaddr,
|
||||
&dgid_addr._sockaddr, &dev_addr);
|
||||
if (sa_path_is_roce(rec)) {
|
||||
ret = roce_resolve_route_from_path(device, port_num, rec);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((dev_addr.network == RDMA_NETWORK_IPV4 ||
|
||||
dev_addr.network == RDMA_NETWORK_IPV6) &&
|
||||
rec->rec_type != SA_PATH_REC_TYPE_ROCE_V2)
|
||||
return -EINVAL;
|
||||
memcpy(ah_attr->roce.dmac, sa_path_get_dmac(rec), ETH_ALEN);
|
||||
} else {
|
||||
rdma_ah_set_dlid(ah_attr, be32_to_cpu(sa_path_get_dlid(rec)));
|
||||
if (sa_path_is_opa(rec) &&
|
||||
rdma_ah_get_dlid(ah_attr) == be16_to_cpu(IB_LID_PERMISSIVE))
|
||||
rdma_ah_set_make_grd(ah_attr, true);
|
||||
|
||||
idev = device->get_netdev(device, port_num);
|
||||
if (!idev)
|
||||
return -ENODEV;
|
||||
|
||||
resolved_dev = dev_get_by_index(dev_addr.net,
|
||||
dev_addr.bound_dev_if);
|
||||
if (!resolved_dev) {
|
||||
dev_put(idev);
|
||||
return -ENODEV;
|
||||
}
|
||||
ndev = ib_get_ndev_from_path(rec);
|
||||
if ((ndev && ndev != resolved_dev) ||
|
||||
(resolved_dev != idev &&
|
||||
rdma_vlan_dev_real_dev(resolved_dev) != idev))
|
||||
ret = -EHOSTUNREACH;
|
||||
dev_put(idev);
|
||||
dev_put(resolved_dev);
|
||||
if (ret) {
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
return ret;
|
||||
}
|
||||
rdma_ah_set_path_bits(ah_attr,
|
||||
be32_to_cpu(sa_path_get_slid(rec)) &
|
||||
get_src_path_mask(device, port_num));
|
||||
}
|
||||
|
||||
if (rec->hop_limit > 0 || use_roce) {
|
||||
enum ib_gid_type type = sa_conv_pathrec_to_gid_type(rec);
|
||||
|
||||
ret = ib_find_cached_gid_by_port(device, &rec->sgid, type,
|
||||
port_num, ndev, &gid_index);
|
||||
if (ret) {
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdma_ah_set_grh(ah_attr, &rec->dgid,
|
||||
be32_to_cpu(rec->flow_label),
|
||||
gid_index, rec->hop_limit,
|
||||
rec->traffic_class);
|
||||
if (ndev)
|
||||
dev_put(ndev);
|
||||
}
|
||||
|
||||
if (use_roce) {
|
||||
u8 *dmac = sa_path_get_dmac(rec);
|
||||
|
||||
if (!dmac)
|
||||
return -EINVAL;
|
||||
memcpy(ah_attr->roce.dmac, dmac, ETH_ALEN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (rec->hop_limit > 0 || sa_path_is_roce(rec))
|
||||
ret = init_ah_attr_grh_fields(device, port_num, rec, ah_attr);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_init_ah_attr_from_path);
|
||||
|
||||
|
||||
@@ -411,6 +411,7 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
|
||||
{
|
||||
struct port_table_attribute *tab_attr =
|
||||
container_of(attr, struct port_table_attribute, attr);
|
||||
union ib_gid *pgid;
|
||||
union ib_gid gid;
|
||||
ssize_t ret;
|
||||
|
||||
@@ -418,7 +419,20 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, GID_PRINT_FMT"\n", GID_PRINT_ARGS(gid.raw));
|
||||
/* If reading GID fails, it is likely due to GID entry being empty
|
||||
* (invalid) or reserved GID in the table.
|
||||
* User space expects to read GID table entries as long as it given
|
||||
* index is within GID table size.
|
||||
* Administrative/debugging tool fails to query rest of the GID entries
|
||||
* if it hits error while querying a GID of the given index.
|
||||
* To avoid user space throwing such error on fail to read gid, return
|
||||
* zero GID as before. This maintains backward compatibility.
|
||||
*/
|
||||
if (ret)
|
||||
pgid = &zgid;
|
||||
else
|
||||
pgid = &gid;
|
||||
return sprintf(buf, GID_PRINT_FMT"\n", GID_PRINT_ARGS(pgid->raw));
|
||||
}
|
||||
|
||||
static ssize_t show_port_gid_attr_ndev(struct ib_port *p,
|
||||
|
||||
@@ -1248,6 +1248,9 @@ static int ucma_set_ib_path(struct ucma_context *ctx,
|
||||
if (!optlen)
|
||||
return -EINVAL;
|
||||
|
||||
if (!ctx->cm_id->device)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&sa_path, 0, sizeof(sa_path));
|
||||
|
||||
sa_path.rec_type = SA_PATH_REC_TYPE_IB;
|
||||
|
||||
@@ -66,8 +66,6 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
|
||||
}
|
||||
|
||||
sg_free_table(&umem->sg_head);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,11 +56,6 @@
|
||||
#define net_eq(a,b) ((a) == (b))
|
||||
|
||||
|
||||
struct rdma_addr_client {
|
||||
atomic_t refcount;
|
||||
struct completion comp;
|
||||
};
|
||||
|
||||
union rdma_sockaddr {
|
||||
struct sockaddr _sockaddr;
|
||||
struct sockaddr_in _sockaddr_in;
|
||||
@@ -68,17 +63,6 @@ union rdma_sockaddr {
|
||||
struct sockaddr_storage _sockaddr_ss;
|
||||
};
|
||||
|
||||
/**
|
||||
* rdma_addr_register_client - Register an address client.
|
||||
*/
|
||||
void rdma_addr_register_client(struct rdma_addr_client *client);
|
||||
|
||||
/**
|
||||
* rdma_addr_unregister_client - Deregister an address client.
|
||||
* @client: Client object to deregister.
|
||||
*/
|
||||
void rdma_addr_unregister_client(struct rdma_addr_client *client);
|
||||
|
||||
/**
|
||||
* struct rdma_dev_addr - Contains resolved RDMA hardware addresses
|
||||
* @src_dev_addr: Source MAC address.
|
||||
@@ -114,7 +98,6 @@ int rdma_translate_ip(const struct sockaddr *addr,
|
||||
/**
|
||||
* rdma_resolve_ip - Resolve source and destination IP addresses to
|
||||
* RDMA hardware addresses.
|
||||
* @client: Address client associated with request.
|
||||
* @src_addr: An optional source address to use in the resolution. If a
|
||||
* source address is not provided, a usable address will be returned via
|
||||
* the callback.
|
||||
@@ -127,17 +110,12 @@ int rdma_translate_ip(const struct sockaddr *addr,
|
||||
* or been canceled. A status of 0 indicates success.
|
||||
* @context: User-specified context associated with the call.
|
||||
*/
|
||||
int rdma_resolve_ip(struct rdma_addr_client *client,
|
||||
struct sockaddr *src_addr, struct sockaddr *dst_addr,
|
||||
int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
|
||||
struct rdma_dev_addr *addr, int timeout_ms,
|
||||
void (*callback)(int status, struct sockaddr *src_addr,
|
||||
struct rdma_dev_addr *addr, void *context),
|
||||
void *context);
|
||||
|
||||
int rdma_resolve_ip_route(struct sockaddr *src_addr,
|
||||
const struct sockaddr *dst_addr,
|
||||
struct rdma_dev_addr *addr);
|
||||
|
||||
void rdma_addr_cancel(struct rdma_dev_addr *addr);
|
||||
|
||||
void rdma_copy_addr(struct rdma_dev_addr *dev_addr,
|
||||
@@ -148,11 +126,6 @@ int rdma_addr_size(struct sockaddr *addr);
|
||||
int rdma_addr_size_in6(struct sockaddr_in6 *addr);
|
||||
int rdma_addr_size_kss(struct sockaddr_storage *addr);
|
||||
|
||||
int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
|
||||
const union ib_gid *dgid,
|
||||
u8 *dmac, if_t ndev,
|
||||
int *hoplimit);
|
||||
|
||||
static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)
|
||||
{
|
||||
return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9];
|
||||
|
||||
@@ -57,20 +57,6 @@ int ib_get_cached_gid(struct ib_device *device,
|
||||
union ib_gid *gid,
|
||||
struct ib_gid_attr *attr);
|
||||
|
||||
/**
|
||||
* ib_find_cached_gid - Returns the port number and GID table index where
|
||||
* a specified GID value occurs.
|
||||
* @device: The device to query.
|
||||
* @gid: The GID value to search for.
|
||||
* @gid_type: The GID type to search for.
|
||||
* @ndev: In RoCE, the net device of the device. NULL means ignore.
|
||||
* @port_num: The port number of the device where the GID value was found.
|
||||
* @index: The index into the cached GID table where the GID was found. This
|
||||
* parameter may be NULL.
|
||||
*
|
||||
* ib_find_cached_gid() searches for the specified GID value in
|
||||
* the local software cache.
|
||||
*/
|
||||
int ib_find_cached_gid(struct ib_device *device,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
@@ -78,21 +64,6 @@ int ib_find_cached_gid(struct ib_device *device,
|
||||
u8 *port_num,
|
||||
u16 *index);
|
||||
|
||||
/**
|
||||
* ib_find_cached_gid_by_port - Returns the GID table index where a specified
|
||||
* GID value occurs
|
||||
* @device: The device to query.
|
||||
* @gid: The GID value to search for.
|
||||
* @gid_type: The GID type to search for.
|
||||
* @port_num: The port number of the device where the GID value sould be
|
||||
* searched.
|
||||
* @ndev: In RoCE, the net device of the device. Null means ignore.
|
||||
* @index: The index into the cached GID table where the GID was found. This
|
||||
* parameter may be NULL.
|
||||
*
|
||||
* ib_find_cached_gid() searches for the specified GID value in
|
||||
* the local software cache.
|
||||
*/
|
||||
int ib_find_cached_gid_by_port(struct ib_device *device,
|
||||
const union ib_gid *gid,
|
||||
enum ib_gid_type gid_type,
|
||||
|
||||
@@ -164,7 +164,15 @@ struct sa_path_rec_ib {
|
||||
u8 raw_traffic;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sa_path_rec_roce - RoCE specific portion of the path record entry
|
||||
* @route_resolved: When set, it indicates that this route is already
|
||||
* resolved for this path record entry.
|
||||
* @dmac: Destination mac address for the given DGID entry
|
||||
* of the path record entry.
|
||||
*/
|
||||
struct sa_path_rec_roce {
|
||||
bool route_resolved;
|
||||
u8 dmac[ETH_ALEN];
|
||||
/* ignored in IB */
|
||||
int ifindex;
|
||||
@@ -591,6 +599,11 @@ static inline bool sa_path_is_roce(struct sa_path_rec *rec)
|
||||
(rec->rec_type == SA_PATH_REC_TYPE_ROCE_V2));
|
||||
}
|
||||
|
||||
static inline bool sa_path_is_opa(struct sa_path_rec *rec)
|
||||
{
|
||||
return (rec->rec_type == SA_PATH_REC_TYPE_OPA);
|
||||
}
|
||||
|
||||
static inline void sa_path_set_slid(struct sa_path_rec *rec, __be32 slid)
|
||||
{
|
||||
if (rec->rec_type == SA_PATH_REC_TYPE_IB)
|
||||
|
||||
@@ -103,8 +103,11 @@ enum ib_gid_type {
|
||||
|
||||
#define ROCE_V2_UDP_DPORT 4791
|
||||
struct ib_gid_attr {
|
||||
enum ib_gid_type gid_type;
|
||||
if_t ndev;
|
||||
struct ib_device *device;
|
||||
enum ib_gid_type gid_type;
|
||||
u16 index;
|
||||
u8 port_num;
|
||||
};
|
||||
|
||||
enum rdma_node_type {
|
||||
@@ -2182,37 +2185,36 @@ struct ib_device {
|
||||
*/
|
||||
if_t (*get_netdev)(struct ib_device *device,
|
||||
u8 port_num);
|
||||
/* query_gid should be return GID value for @device, when @port_num
|
||||
* link layer is either IB or iWarp. It is no-op if @port_num port
|
||||
* is RoCE link layer.
|
||||
*/
|
||||
int (*query_gid)(struct ib_device *device,
|
||||
u8 port_num, int index,
|
||||
union ib_gid *gid);
|
||||
/* When calling add_gid, the HW vendor's driver should
|
||||
* add the gid of device @device at gid index @index of
|
||||
* port @port_num to be @gid. Meta-info of that gid (for example,
|
||||
* the network device related to this gid is available
|
||||
* at @attr. @context allows the HW vendor driver to store extra
|
||||
* information together with a GID entry. The HW vendor may allocate
|
||||
* memory to contain this information and store it in @context when a
|
||||
* new GID entry is written to. Params are consistent until the next
|
||||
* call of add_gid or delete_gid. The function should return 0 on
|
||||
/* When calling add_gid, the HW vendor's driver should add the gid
|
||||
* of device of port at gid index available at @attr. Meta-info of
|
||||
* that gid (for example, the network device related to this gid) is
|
||||
* available at @attr. @context allows the HW vendor driver to store
|
||||
* extra information together with a GID entry. The HW vendor driver may
|
||||
* allocate memory to contain this information and store it in @context
|
||||
* when a new GID entry is written to. Params are consistent until the
|
||||
* next call of add_gid or delete_gid. The function should return 0 on
|
||||
* success or error otherwise. The function could be called
|
||||
* concurrently for different ports. This function is only called
|
||||
* when roce_gid_table is used.
|
||||
* concurrently for different ports. This function is only called when
|
||||
* roce_gid_table is used.
|
||||
*/
|
||||
int (*add_gid)(struct ib_device *device,
|
||||
u8 port_num,
|
||||
unsigned int index,
|
||||
const union ib_gid *gid,
|
||||
int (*add_gid)(const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr,
|
||||
void **context);
|
||||
/* When calling del_gid, the HW vendor's driver should delete the
|
||||
* gid of device @device at gid index @index of port @port_num.
|
||||
* gid of device @device at gid index gid_index of port port_num
|
||||
* available in @attr.
|
||||
* Upon the deletion of a GID entry, the HW vendor must free any
|
||||
* allocated memory. The caller will clear @context afterwards.
|
||||
* This function is only called when roce_gid_table is used.
|
||||
*/
|
||||
int (*del_gid)(struct ib_device *device,
|
||||
u8 port_num,
|
||||
unsigned int index,
|
||||
int (*del_gid)(const struct ib_gid_attr *attr,
|
||||
void **context);
|
||||
int (*query_pkey)(struct ib_device *device,
|
||||
u8 port_num, u16 index, u16 *pkey);
|
||||
@@ -2960,7 +2962,7 @@ int ib_modify_port(struct ib_device *device,
|
||||
struct ib_port_modify *port_modify);
|
||||
|
||||
int ib_find_gid(struct ib_device *device, union ib_gid *gid,
|
||||
if_t ndev, u8 *port_num, u16 *index);
|
||||
u8 *port_num, u16 *index);
|
||||
|
||||
int ib_find_pkey(struct ib_device *device,
|
||||
u8 port_num, u16 pkey, u16 *index);
|
||||
|
||||
@@ -122,20 +122,6 @@ struct rdma_cm_event {
|
||||
} param;
|
||||
};
|
||||
|
||||
enum rdma_cm_state {
|
||||
RDMA_CM_IDLE,
|
||||
RDMA_CM_ADDR_QUERY,
|
||||
RDMA_CM_ADDR_RESOLVED,
|
||||
RDMA_CM_ROUTE_QUERY,
|
||||
RDMA_CM_ROUTE_RESOLVED,
|
||||
RDMA_CM_CONNECT,
|
||||
RDMA_CM_DISCONNECT,
|
||||
RDMA_CM_ADDR_BOUND,
|
||||
RDMA_CM_LISTEN,
|
||||
RDMA_CM_DEVICE_REMOVAL,
|
||||
RDMA_CM_DESTROYING
|
||||
};
|
||||
|
||||
struct rdma_cm_id;
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user