mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:02:20 +00:00
RDMA: Introduce and use GID attr helper to read RoCE L2 fields
Instead of RoCE drivers figuring out vlan, smac fields while working on QP/AH, provide a helper routine to read the L2 fields such as vlan_id and source mac address. This moves logic from mlx5 driver to core for wider usage for RoCE ports. This is a preparation patch to allow detaching netdev in subsequent patch. Signed-off-by: Parav Pandit <parav@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
8f97486024
commit
a70c07397f
@ -1250,6 +1250,61 @@ struct net_device *rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr)
|
||||
return ndev;
|
||||
}
|
||||
|
||||
static int get_lower_dev_vlan(struct net_device *lower_dev, void *data)
|
||||
{
|
||||
u16 *vlan_id = data;
|
||||
|
||||
if (is_vlan_dev(lower_dev))
|
||||
*vlan_id = vlan_dev_vlan_id(lower_dev);
|
||||
|
||||
/* We are interested only in first level vlan device, so
|
||||
* always return 1 to stop iterating over next level devices.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* rdma_read_gid_l2_fields - Read the vlan ID and source MAC address
|
||||
* of a GID entry.
|
||||
*
|
||||
* @attr: GID attribute pointer whose L2 fields to be read
|
||||
* @vlan_id: Pointer to vlan id to fill up if the GID entry has
|
||||
* vlan id. It is optional.
|
||||
* @smac: Pointer to smac to fill up for a GID entry. It is optional.
|
||||
*
|
||||
* rdma_read_gid_l2_fields() returns 0 on success and returns vlan id
|
||||
* (if gid entry has vlan) and source MAC, or returns error.
|
||||
*/
|
||||
int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
|
||||
u16 *vlan_id, u8 *smac)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
|
||||
ndev = attr->ndev;
|
||||
if (!ndev)
|
||||
return -EINVAL;
|
||||
|
||||
if (smac)
|
||||
ether_addr_copy(smac, ndev->dev_addr);
|
||||
if (vlan_id) {
|
||||
*vlan_id = 0xffff;
|
||||
if (is_vlan_dev(ndev)) {
|
||||
*vlan_id = vlan_dev_vlan_id(ndev);
|
||||
} else {
|
||||
/* If the netdev is upper device and if it's lower
|
||||
* device is vlan device, consider vlan id of the
|
||||
* the lower vlan device for this gid entry.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
netdev_walk_all_lower_dev_rcu(attr->ndev,
|
||||
get_lower_dev_vlan, vlan_id);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rdma_read_gid_l2_fields);
|
||||
|
||||
static int config_non_roce_gid_cache(struct ib_device *device,
|
||||
u8 port, int gid_tbl_len)
|
||||
{
|
||||
|
@ -360,8 +360,9 @@ int bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context)
|
||||
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);
|
||||
rc = rdma_read_gid_l2_fields(attr, &vlan_id, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = bnxt_qplib_add_sgid(sgid_tbl, (struct bnxt_qplib_gid *)&attr->gid,
|
||||
rdev->qplib_res.netdev->dev_addr,
|
||||
@ -1637,8 +1638,11 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
||||
qp_attr->ah_attr.roce.dmac);
|
||||
|
||||
sgid_attr = qp_attr->ah_attr.grh.sgid_attr;
|
||||
memcpy(qp->qplib_qp.smac, sgid_attr->ndev->dev_addr,
|
||||
ETH_ALEN);
|
||||
rc = rdma_read_gid_l2_fields(sgid_attr, NULL,
|
||||
&qp->qplib_qp.smac[0]);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
nw_type = rdma_gid_attr_network_type(sgid_attr);
|
||||
switch (nw_type) {
|
||||
case RDMA_NETWORK_IPV4:
|
||||
@ -1857,8 +1861,10 @@ static int bnxt_re_build_qp1_send_v2(struct bnxt_re_qp *qp,
|
||||
|
||||
memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr));
|
||||
|
||||
if (is_vlan_dev(sgid_attr->ndev))
|
||||
vlan_id = vlan_dev_vlan_id(sgid_attr->ndev);
|
||||
rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Get network header type for this GID */
|
||||
nw_type = rdma_gid_attr_network_type(sgid_attr);
|
||||
switch (nw_type) {
|
||||
|
@ -49,20 +49,22 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
|
||||
u16 vlan_tag = 0xffff;
|
||||
const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
|
||||
bool vlan_en = false;
|
||||
int ret;
|
||||
|
||||
gid_attr = ah_attr->grh.sgid_attr;
|
||||
ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get mac address */
|
||||
memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);
|
||||
|
||||
gid_attr = ah_attr->grh.sgid_attr;
|
||||
if (is_vlan_dev(gid_attr->ndev)) {
|
||||
vlan_tag = vlan_dev_vlan_id(gid_attr->ndev);
|
||||
if (vlan_tag < VLAN_CFI_MASK) {
|
||||
vlan_en = true;
|
||||
}
|
||||
|
||||
if (vlan_tag < 0x1000)
|
||||
vlan_tag |= (rdma_ah_get_sl(ah_attr) &
|
||||
HNS_ROCE_VLAN_SL_BIT_MASK) <<
|
||||
HNS_ROCE_VLAN_SL_SHIFT;
|
||||
}
|
||||
|
||||
ah->av.port_pd = cpu_to_le32(to_hr_pd(ibah->pd)->pdn |
|
||||
(rdma_ah_get_port_num(ah_attr) <<
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <rdma/ib_addr.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
#include <rdma/ib_umem.h>
|
||||
#include <rdma/uverbs_ioctl.h>
|
||||
|
||||
@ -3984,10 +3985,12 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
|
||||
|
||||
if (is_roce_protocol) {
|
||||
gid_attr = attr->ah_attr.grh.sgid_attr;
|
||||
vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev);
|
||||
ret = rdma_read_gid_l2_fields(gid_attr, &vlan, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_vlan_dev(gid_attr->ndev)) {
|
||||
if (vlan < VLAN_CFI_MASK) {
|
||||
roce_set_bit(context->byte_76_srqn_op_en,
|
||||
V2_QPC_BYTE_76_RQ_VLAN_EN_S, 1);
|
||||
roce_set_bit(qpc_mask->byte_76_srqn_op_en,
|
||||
|
@ -99,9 +99,11 @@ static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
|
||||
*/
|
||||
gid_attr = ah_attr->grh.sgid_attr;
|
||||
if (gid_attr) {
|
||||
if (is_vlan_dev(gid_attr->ndev))
|
||||
vlan_tag = vlan_dev_vlan_id(gid_attr->ndev);
|
||||
memcpy(ah->av.eth.s_mac, gid_attr->ndev->dev_addr, ETH_ALEN);
|
||||
ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag,
|
||||
&ah->av.eth.s_mac[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -2248,8 +2248,10 @@ static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type,
|
||||
|
||||
if (is_eth) {
|
||||
gid_attr = attr->ah_attr.grh.sgid_attr;
|
||||
vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev);
|
||||
memcpy(smac, gid_attr->ndev->dev_addr, ETH_ALEN);
|
||||
err = rdma_read_gid_l2_fields(gid_attr, &vlan,
|
||||
&smac[0]);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path,
|
||||
|
@ -574,52 +574,22 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
struct mlx5_ib_vlan_info {
|
||||
u16 vlan_id;
|
||||
bool vlan;
|
||||
};
|
||||
|
||||
static int get_lower_dev_vlan(struct net_device *lower_dev, void *data)
|
||||
{
|
||||
struct mlx5_ib_vlan_info *vlan_info = data;
|
||||
|
||||
if (is_vlan_dev(lower_dev)) {
|
||||
vlan_info->vlan = true;
|
||||
vlan_info->vlan_id = vlan_dev_vlan_id(lower_dev);
|
||||
}
|
||||
/* We are interested only in first level vlan device, so
|
||||
* always return 1 to stop iterating over next level devices.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_roce_addr(struct mlx5_ib_dev *dev, u8 port_num,
|
||||
unsigned int index, const union ib_gid *gid,
|
||||
const struct ib_gid_attr *attr)
|
||||
{
|
||||
enum ib_gid_type gid_type = IB_GID_TYPE_IB;
|
||||
struct mlx5_ib_vlan_info vlan_info = { };
|
||||
u16 vlan_id = 0xffff;
|
||||
u8 roce_version = 0;
|
||||
u8 roce_l3_type = 0;
|
||||
u8 mac[ETH_ALEN];
|
||||
int ret;
|
||||
|
||||
if (gid) {
|
||||
gid_type = attr->gid_type;
|
||||
ether_addr_copy(mac, attr->ndev->dev_addr);
|
||||
|
||||
if (is_vlan_dev(attr->ndev)) {
|
||||
vlan_info.vlan = true;
|
||||
vlan_info.vlan_id = vlan_dev_vlan_id(attr->ndev);
|
||||
} else {
|
||||
/* If the netdev is upper device and if it's lower
|
||||
* lower device is vlan device, consider vlan id of
|
||||
* the lower vlan device for this gid entry.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
netdev_walk_all_lower_dev_rcu(attr->ndev,
|
||||
get_lower_dev_vlan, &vlan_info);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
ret = rdma_read_gid_l2_fields(attr, &vlan_id, &mac[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (gid_type) {
|
||||
@ -640,7 +610,7 @@ static int set_roce_addr(struct mlx5_ib_dev *dev, u8 port_num,
|
||||
|
||||
return mlx5_core_roce_gid_set(dev->mdev, index, roce_version,
|
||||
roce_l3_type, gid->raw, mac,
|
||||
vlan_info.vlan, vlan_info.vlan_id,
|
||||
vlan_id < VLAN_CFI_MASK, vlan_id,
|
||||
port_num);
|
||||
}
|
||||
|
||||
|
@ -175,14 +175,15 @@ int ocrdma_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr, u32 flags,
|
||||
if (atomic_cmpxchg(&dev->update_sl, 1, 0))
|
||||
ocrdma_init_service_level(dev);
|
||||
|
||||
sgid_attr = attr->grh.sgid_attr;
|
||||
status = rdma_read_gid_l2_fields(sgid_attr, &vlan_tag, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = ocrdma_alloc_av(dev, ah);
|
||||
if (status)
|
||||
goto av_err;
|
||||
|
||||
sgid_attr = attr->grh.sgid_attr;
|
||||
if (is_vlan_dev(sgid_attr->ndev))
|
||||
vlan_tag = vlan_dev_vlan_id(sgid_attr->ndev);
|
||||
|
||||
/* Get network header type for this GID */
|
||||
ah->hdr_type = rdma_gid_attr_network_type(sgid_attr);
|
||||
|
||||
|
@ -2496,7 +2496,7 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
|
||||
int status;
|
||||
struct rdma_ah_attr *ah_attr = &attrs->ah_attr;
|
||||
const struct ib_gid_attr *sgid_attr;
|
||||
u32 vlan_id = 0xFFFF;
|
||||
u16 vlan_id = 0xFFFF;
|
||||
u8 mac_addr[6], hdr_type;
|
||||
union {
|
||||
struct sockaddr _sockaddr;
|
||||
@ -2526,8 +2526,9 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
|
||||
sizeof(cmd->params.dgid));
|
||||
|
||||
sgid_attr = ah_attr->grh.sgid_attr;
|
||||
vlan_id = rdma_vlan_dev_vlan_id(sgid_attr->ndev);
|
||||
memcpy(mac_addr, sgid_attr->ndev->dev_addr, ETH_ALEN);
|
||||
status = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, &mac_addr[0]);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
qp->sgid_idx = grh->sgid_index;
|
||||
memcpy(&cmd->params.sgid[0], &sgid_attr->gid.raw[0],
|
||||
|
@ -397,14 +397,17 @@ static inline int qedr_gsi_build_header(struct qedr_dev *dev,
|
||||
bool has_udp = false;
|
||||
int i;
|
||||
|
||||
rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (vlan_id < VLAN_CFI_MASK)
|
||||
has_vlan = true;
|
||||
|
||||
send_size = 0;
|
||||
for (i = 0; i < swr->num_sge; ++i)
|
||||
send_size += swr->sg_list[i].length;
|
||||
|
||||
vlan_id = rdma_vlan_dev_vlan_id(sgid_attr->ndev);
|
||||
if (vlan_id < VLAN_CFI_MASK)
|
||||
has_vlan = true;
|
||||
|
||||
has_udp = (sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP);
|
||||
if (!has_udp) {
|
||||
/* RoCE v1 */
|
||||
|
@ -1050,10 +1050,13 @@ static inline int get_gid_info_from_table(struct ib_qp *ibqp,
|
||||
enum rdma_network_type nw_type;
|
||||
const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr);
|
||||
u32 ipv4_addr;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
gid_attr = grh->sgid_attr;
|
||||
qp_params->vlan_id = rdma_vlan_dev_vlan_id(gid_attr->ndev);
|
||||
ret = rdma_read_gid_l2_fields(gid_attr, &qp_params->vlan_id, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nw_type = rdma_gid_attr_network_type(gid_attr);
|
||||
switch (nw_type) {
|
||||
|
@ -54,6 +54,9 @@ const struct ib_gid_attr *rdma_find_gid_by_filter(
|
||||
void *),
|
||||
void *context);
|
||||
|
||||
int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
|
||||
u16 *vlan_id, u8 *smac);
|
||||
|
||||
/**
|
||||
* ib_get_cached_pkey - Returns a cached PKey table entry
|
||||
* @device: The device to query.
|
||||
|
Loading…
Reference in New Issue
Block a user