Commit c56b593d authored by Selvin Xavier's avatar Selvin Xavier Committed by Jason Gunthorpe

RDMA/bnxt_re: Honor vlan_id in GID entry comparison

A GID entry consists of GID, vlan, netdev and smac.  Extend GID duplicate
check comparisons to consider vlan_id as well to support IPv6 VLAN based
link local addresses. Introduce a new structure (bnxt_qplib_gid_info) to
hold gid and vlan_id information.

The issue is discussed in the following thread
https://lore.kernel.org/r/AM0PR05MB4866CFEDCDF3CDA1D7D18AA5D1F20@AM0PR05MB4866.eurprd05.prod.outlook.com

Fixes: 823b23da ("IB/core: Allow vlan link local address based RoCE GIDs")
Cc: <stable@vger.kernel.org> # v5.2+
Link: https://lore.kernel.org/r/20190715091913.15726-1-selvin.xavier@broadcom.comReported-by: default avatarYi Zhang <yi.zhang@redhat.com>
Co-developed-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarSelvin Xavier <selvin.xavier@broadcom.com>
Tested-by: default avatarYi Zhang <yi.zhang@redhat.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent f4d46119
...@@ -308,6 +308,7 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context) ...@@ -308,6 +308,7 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, 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_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
struct bnxt_qplib_gid *gid_to_del; struct bnxt_qplib_gid *gid_to_del;
u16 vlan_id = 0xFFFF;
/* Delete the entry from the hardware */ /* Delete the entry from the hardware */
ctx = *context; ctx = *context;
...@@ -317,7 +318,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context) ...@@ -317,7 +318,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
if (sgid_tbl && sgid_tbl->active) { if (sgid_tbl && sgid_tbl->active) {
if (ctx->idx >= sgid_tbl->max) if (ctx->idx >= sgid_tbl->max)
return -EINVAL; return -EINVAL;
gid_to_del = &sgid_tbl->tbl[ctx->idx]; gid_to_del = &sgid_tbl->tbl[ctx->idx].gid;
vlan_id = sgid_tbl->tbl[ctx->idx].vlan_id;
/* DEL_GID is called in WQ context(netdevice_event_work_handler) /* DEL_GID is called in WQ context(netdevice_event_work_handler)
* or via the ib_unregister_device path. In the former case QP1 * or via the ib_unregister_device path. In the former case QP1
* may not be destroyed yet, in which case just return as FW * may not be destroyed yet, in which case just return as FW
...@@ -335,7 +337,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context) ...@@ -335,7 +337,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
} }
ctx->refcnt--; ctx->refcnt--;
if (!ctx->refcnt) { if (!ctx->refcnt) {
rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del, true); rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del,
vlan_id, true);
if (rc) { if (rc) {
dev_err(rdev_to_dev(rdev), dev_err(rdev_to_dev(rdev),
"Failed to remove GID: %#x", rc); "Failed to remove GID: %#x", rc);
......
...@@ -488,7 +488,7 @@ static int bnxt_qplib_alloc_sgid_tbl(struct bnxt_qplib_res *res, ...@@ -488,7 +488,7 @@ static int bnxt_qplib_alloc_sgid_tbl(struct bnxt_qplib_res *res,
struct bnxt_qplib_sgid_tbl *sgid_tbl, struct bnxt_qplib_sgid_tbl *sgid_tbl,
u16 max) u16 max)
{ {
sgid_tbl->tbl = kcalloc(max, sizeof(struct bnxt_qplib_gid), GFP_KERNEL); sgid_tbl->tbl = kcalloc(max, sizeof(*sgid_tbl->tbl), GFP_KERNEL);
if (!sgid_tbl->tbl) if (!sgid_tbl->tbl)
return -ENOMEM; return -ENOMEM;
...@@ -526,9 +526,10 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res, ...@@ -526,9 +526,10 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res,
for (i = 0; i < sgid_tbl->max; i++) { for (i = 0; i < sgid_tbl->max; i++) {
if (memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, if (memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero,
sizeof(bnxt_qplib_gid_zero))) sizeof(bnxt_qplib_gid_zero)))
bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i], true); bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i].gid,
sgid_tbl->tbl[i].vlan_id, true);
} }
memset(sgid_tbl->tbl, 0, sizeof(struct bnxt_qplib_gid) * sgid_tbl->max); memset(sgid_tbl->tbl, 0, sizeof(*sgid_tbl->tbl) * sgid_tbl->max);
memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max); memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
memset(sgid_tbl->vlan, 0, sizeof(u8) * sgid_tbl->max); memset(sgid_tbl->vlan, 0, sizeof(u8) * sgid_tbl->max);
sgid_tbl->active = 0; sgid_tbl->active = 0;
...@@ -537,7 +538,11 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res, ...@@ -537,7 +538,11 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res,
static void bnxt_qplib_init_sgid_tbl(struct bnxt_qplib_sgid_tbl *sgid_tbl, static void bnxt_qplib_init_sgid_tbl(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct net_device *netdev) struct net_device *netdev)
{ {
memset(sgid_tbl->tbl, 0, sizeof(struct bnxt_qplib_gid) * sgid_tbl->max); u32 i;
for (i = 0; i < sgid_tbl->max; i++)
sgid_tbl->tbl[i].vlan_id = 0xffff;
memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max); memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
} }
......
...@@ -111,7 +111,7 @@ struct bnxt_qplib_pd_tbl { ...@@ -111,7 +111,7 @@ struct bnxt_qplib_pd_tbl {
}; };
struct bnxt_qplib_sgid_tbl { struct bnxt_qplib_sgid_tbl {
struct bnxt_qplib_gid *tbl; struct bnxt_qplib_gid_info *tbl;
u16 *hw_id; u16 *hw_id;
u16 max; u16 max;
u16 active; u16 active;
......
...@@ -213,12 +213,12 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, ...@@ -213,12 +213,12 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
index, sgid_tbl->max); index, sgid_tbl->max);
return -EINVAL; return -EINVAL;
} }
memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid)); memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid));
return 0; return 0;
} }
int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_gid *gid, bool update) struct bnxt_qplib_gid *gid, u16 vlan_id, bool update)
{ {
struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
struct bnxt_qplib_res, struct bnxt_qplib_res,
...@@ -236,7 +236,8 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -236,7 +236,8 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
return -ENOMEM; return -ENOMEM;
} }
for (index = 0; index < sgid_tbl->max; index++) { for (index = 0; index < sgid_tbl->max; index++) {
if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid))) if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) &&
vlan_id == sgid_tbl->tbl[index].vlan_id)
break; break;
} }
if (index == sgid_tbl->max) { if (index == sgid_tbl->max) {
...@@ -262,8 +263,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -262,8 +263,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
if (rc) if (rc)
return rc; return rc;
} }
memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero, memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero,
sizeof(bnxt_qplib_gid_zero)); sizeof(bnxt_qplib_gid_zero));
sgid_tbl->tbl[index].vlan_id = 0xFFFF;
sgid_tbl->vlan[index] = 0; sgid_tbl->vlan[index] = 0;
sgid_tbl->active--; sgid_tbl->active--;
dev_dbg(&res->pdev->dev, dev_dbg(&res->pdev->dev,
...@@ -296,7 +298,8 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -296,7 +298,8 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
} }
free_idx = sgid_tbl->max; free_idx = sgid_tbl->max;
for (i = 0; i < sgid_tbl->max; i++) { for (i = 0; i < sgid_tbl->max; i++) {
if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) { if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) &&
sgid_tbl->tbl[i].vlan_id == vlan_id) {
dev_dbg(&res->pdev->dev, dev_dbg(&res->pdev->dev,
"SGID entry already exist in entry %d!\n", i); "SGID entry already exist in entry %d!\n", i);
*index = i; *index = i;
...@@ -351,6 +354,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -351,6 +354,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
} }
/* Add GID to the sgid_tbl */ /* Add GID to the sgid_tbl */
memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
sgid_tbl->tbl[free_idx].vlan_id = vlan_id;
sgid_tbl->active++; sgid_tbl->active++;
if (vlan_id != 0xFFFF) if (vlan_id != 0xFFFF)
sgid_tbl->vlan[free_idx] = 1; sgid_tbl->vlan[free_idx] = 1;
......
...@@ -84,6 +84,11 @@ struct bnxt_qplib_gid { ...@@ -84,6 +84,11 @@ struct bnxt_qplib_gid {
u8 data[16]; u8 data[16];
}; };
struct bnxt_qplib_gid_info {
struct bnxt_qplib_gid gid;
u16 vlan_id;
};
struct bnxt_qplib_ah { struct bnxt_qplib_ah {
struct bnxt_qplib_gid dgid; struct bnxt_qplib_gid dgid;
struct bnxt_qplib_pd *pd; struct bnxt_qplib_pd *pd;
...@@ -221,7 +226,7 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, ...@@ -221,7 +226,7 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,
struct bnxt_qplib_gid *gid); struct bnxt_qplib_gid *gid);
int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_gid *gid, bool update); struct bnxt_qplib_gid *gid, u16 vlan_id, bool update);
int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_gid *gid, u8 *mac, u16 vlan_id, struct bnxt_qplib_gid *gid, u8 *mac, u16 vlan_id,
bool update, u32 *index); bool update, u32 *index);
......
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