Merge branch 'ip-roce' into for-next
Conflicts: drivers/infiniband/hw/mlx4/main.c
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
config INFINIBAND_OCRDMA
|
||||
tristate "Emulex One Connect HCA support"
|
||||
depends on ETHERNET && NETDEVICES && PCI && (IPV6 || IPV6=n)
|
||||
depends on ETHERNET && NETDEVICES && PCI && INET && (IPV6 || IPV6=n)
|
||||
select NET_VENDOR_EMULEX
|
||||
select BE2NET
|
||||
---help---
|
||||
|
@@ -423,5 +423,17 @@ static inline int is_cqe_wr_imm(struct ocrdma_cqe *cqe)
|
||||
OCRDMA_CQE_WRITE_IMM) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int ocrdma_resolve_dmac(struct ocrdma_dev *dev,
|
||||
struct ib_ah_attr *ah_attr, u8 *mac_addr)
|
||||
{
|
||||
struct in6_addr in6;
|
||||
|
||||
memcpy(&in6, ah_attr->grh.dgid.raw, sizeof(in6));
|
||||
if (rdma_is_multicast_addr(&in6))
|
||||
rdma_get_mcast_mac(&in6, mac_addr);
|
||||
else
|
||||
memcpy(mac_addr, ah_attr->dmac, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -49,7 +49,7 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
|
||||
|
||||
ah->sgid_index = attr->grh.sgid_index;
|
||||
|
||||
vlan_tag = rdma_get_vlan_id(&attr->grh.dgid);
|
||||
vlan_tag = attr->vlan_id;
|
||||
if (!vlan_tag || (vlan_tag > 0xFFF))
|
||||
vlan_tag = dev->pvid;
|
||||
if (vlan_tag && (vlan_tag < 0x1000)) {
|
||||
@@ -64,7 +64,8 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
|
||||
eth_sz = sizeof(struct ocrdma_eth_basic);
|
||||
}
|
||||
memcpy(ð.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
|
||||
status = ocrdma_resolve_dgid(dev, &attr->grh.dgid, ð.dmac[0]);
|
||||
memcpy(ð.dmac[0], attr->dmac, ETH_ALEN);
|
||||
status = ocrdma_resolve_dmac(dev, attr, ð.dmac[0]);
|
||||
if (status)
|
||||
return status;
|
||||
status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index,
|
||||
|
@@ -2076,23 +2076,6 @@ mbx_err:
|
||||
return status;
|
||||
}
|
||||
|
||||
int ocrdma_resolve_dgid(struct ocrdma_dev *dev, union ib_gid *dgid,
|
||||
u8 *mac_addr)
|
||||
{
|
||||
struct in6_addr in6;
|
||||
|
||||
memcpy(&in6, dgid, sizeof in6);
|
||||
if (rdma_is_multicast_addr(&in6)) {
|
||||
rdma_get_mcast_mac(&in6, mac_addr);
|
||||
} else if (rdma_link_local_addr(&in6)) {
|
||||
rdma_get_ll_mac(&in6, mac_addr);
|
||||
} else {
|
||||
pr_err("%s() fail to resolve mac_addr.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ocrdma_set_av_params(struct ocrdma_qp *qp,
|
||||
struct ocrdma_modify_qp *cmd,
|
||||
struct ib_qp_attr *attrs)
|
||||
@@ -2126,14 +2109,14 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
|
||||
|
||||
qp->sgid_idx = ah_attr->grh.sgid_index;
|
||||
memcpy(&cmd->params.sgid[0], &sgid.raw[0], sizeof(cmd->params.sgid));
|
||||
ocrdma_resolve_dgid(qp->dev, &ah_attr->grh.dgid, &mac_addr[0]);
|
||||
ocrdma_resolve_dmac(qp->dev, ah_attr, &mac_addr[0]);
|
||||
cmd->params.dmac_b0_to_b3 = mac_addr[0] | (mac_addr[1] << 8) |
|
||||
(mac_addr[2] << 16) | (mac_addr[3] << 24);
|
||||
/* convert them to LE format. */
|
||||
ocrdma_cpu_to_le32(&cmd->params.dgid[0], sizeof(cmd->params.dgid));
|
||||
ocrdma_cpu_to_le32(&cmd->params.sgid[0], sizeof(cmd->params.sgid));
|
||||
cmd->params.vlan_dmac_b4_to_b5 = mac_addr[4] | (mac_addr[5] << 8);
|
||||
vlan_id = rdma_get_vlan_id(&sgid);
|
||||
vlan_id = ah_attr->vlan_id;
|
||||
if (vlan_id && (vlan_id < 0x1000)) {
|
||||
cmd->params.vlan_dmac_b4_to_b5 |=
|
||||
vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT;
|
||||
|
@@ -94,7 +94,6 @@ void ocrdma_ring_cq_db(struct ocrdma_dev *, u16 cq_id, bool armed,
|
||||
int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed);
|
||||
int ocrdma_query_config(struct ocrdma_dev *,
|
||||
struct ocrdma_mbx_query_config *config);
|
||||
int ocrdma_resolve_dgid(struct ocrdma_dev *, union ib_gid *dgid, u8 *mac_addr);
|
||||
|
||||
int ocrdma_mbx_alloc_pd(struct ocrdma_dev *, struct ocrdma_pd *);
|
||||
int ocrdma_mbx_dealloc_pd(struct ocrdma_dev *, struct ocrdma_pd *);
|
||||
|
@@ -67,46 +67,24 @@ void ocrdma_get_guid(struct ocrdma_dev *dev, u8 *guid)
|
||||
guid[7] = mac_addr[5];
|
||||
}
|
||||
|
||||
static void ocrdma_build_sgid_mac(union ib_gid *sgid, unsigned char *mac_addr,
|
||||
bool is_vlan, u16 vlan_id)
|
||||
{
|
||||
sgid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
|
||||
sgid->raw[8] = mac_addr[0] ^ 2;
|
||||
sgid->raw[9] = mac_addr[1];
|
||||
sgid->raw[10] = mac_addr[2];
|
||||
if (is_vlan) {
|
||||
sgid->raw[11] = vlan_id >> 8;
|
||||
sgid->raw[12] = vlan_id & 0xff;
|
||||
} else {
|
||||
sgid->raw[11] = 0xff;
|
||||
sgid->raw[12] = 0xfe;
|
||||
}
|
||||
sgid->raw[13] = mac_addr[3];
|
||||
sgid->raw[14] = mac_addr[4];
|
||||
sgid->raw[15] = mac_addr[5];
|
||||
}
|
||||
|
||||
static bool ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
|
||||
bool is_vlan, u16 vlan_id)
|
||||
static bool ocrdma_add_sgid(struct ocrdma_dev *dev, union ib_gid *new_sgid)
|
||||
{
|
||||
int i;
|
||||
union ib_gid new_sgid;
|
||||
unsigned long flags;
|
||||
|
||||
memset(&ocrdma_zero_sgid, 0, sizeof(union ib_gid));
|
||||
|
||||
ocrdma_build_sgid_mac(&new_sgid, mac_addr, is_vlan, vlan_id);
|
||||
|
||||
spin_lock_irqsave(&dev->sgid_lock, flags);
|
||||
for (i = 0; i < OCRDMA_MAX_SGID; i++) {
|
||||
if (!memcmp(&dev->sgid_tbl[i], &ocrdma_zero_sgid,
|
||||
sizeof(union ib_gid))) {
|
||||
/* found free entry */
|
||||
memcpy(&dev->sgid_tbl[i], &new_sgid,
|
||||
memcpy(&dev->sgid_tbl[i], new_sgid,
|
||||
sizeof(union ib_gid));
|
||||
spin_unlock_irqrestore(&dev->sgid_lock, flags);
|
||||
return true;
|
||||
} else if (!memcmp(&dev->sgid_tbl[i], &new_sgid,
|
||||
} else if (!memcmp(&dev->sgid_tbl[i], new_sgid,
|
||||
sizeof(union ib_gid))) {
|
||||
/* entry already present, no addition is required. */
|
||||
spin_unlock_irqrestore(&dev->sgid_lock, flags);
|
||||
@@ -117,20 +95,17 @@ static bool ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ocrdma_del_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
|
||||
bool is_vlan, u16 vlan_id)
|
||||
static bool ocrdma_del_sgid(struct ocrdma_dev *dev, union ib_gid *sgid)
|
||||
{
|
||||
int found = false;
|
||||
int i;
|
||||
union ib_gid sgid;
|
||||
unsigned long flags;
|
||||
|
||||
ocrdma_build_sgid_mac(&sgid, mac_addr, is_vlan, vlan_id);
|
||||
|
||||
spin_lock_irqsave(&dev->sgid_lock, flags);
|
||||
/* first is default sgid, which cannot be deleted. */
|
||||
for (i = 1; i < OCRDMA_MAX_SGID; i++) {
|
||||
if (!memcmp(&dev->sgid_tbl[i], &sgid, sizeof(union ib_gid))) {
|
||||
if (!memcmp(&dev->sgid_tbl[i], sgid, sizeof(union ib_gid))) {
|
||||
/* found matching entry */
|
||||
memset(&dev->sgid_tbl[i], 0, sizeof(union ib_gid));
|
||||
found = true;
|
||||
@@ -141,75 +116,18 @@ static bool ocrdma_del_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
|
||||
return found;
|
||||
}
|
||||
|
||||
static void ocrdma_add_default_sgid(struct ocrdma_dev *dev)
|
||||
static int ocrdma_addr_event(unsigned long event, struct net_device *netdev,
|
||||
union ib_gid *gid)
|
||||
{
|
||||
/* GID Index 0 - Invariant manufacturer-assigned EUI-64 */
|
||||
union ib_gid *sgid = &dev->sgid_tbl[0];
|
||||
|
||||
sgid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
|
||||
ocrdma_get_guid(dev, &sgid->raw[8]);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_VLAN_8021Q)
|
||||
static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev)
|
||||
{
|
||||
struct net_device *netdev, *tmp;
|
||||
u16 vlan_id;
|
||||
bool is_vlan;
|
||||
|
||||
netdev = dev->nic_info.netdev;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_netdev_rcu(&init_net, tmp) {
|
||||
if (netdev == tmp || vlan_dev_real_dev(tmp) == netdev) {
|
||||
if (!netif_running(tmp) || !netif_oper_up(tmp))
|
||||
continue;
|
||||
if (netdev != tmp) {
|
||||
vlan_id = vlan_dev_vlan_id(tmp);
|
||||
is_vlan = true;
|
||||
} else {
|
||||
is_vlan = false;
|
||||
vlan_id = 0;
|
||||
tmp = netdev;
|
||||
}
|
||||
ocrdma_add_sgid(dev, tmp->dev_addr, is_vlan, vlan_id);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
#else
|
||||
static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev)
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* VLAN */
|
||||
|
||||
static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev)
|
||||
{
|
||||
ocrdma_add_default_sgid(dev);
|
||||
ocrdma_add_vlan_sgids(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
||||
static int ocrdma_inet6addr_event(struct notifier_block *notifier,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
|
||||
struct net_device *netdev = ifa->idev->dev;
|
||||
struct ib_event gid_event;
|
||||
struct ocrdma_dev *dev;
|
||||
bool found = false;
|
||||
bool updated = false;
|
||||
bool is_vlan = false;
|
||||
u16 vid = 0;
|
||||
|
||||
is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN;
|
||||
if (is_vlan) {
|
||||
vid = vlan_dev_vlan_id(netdev);
|
||||
if (is_vlan)
|
||||
netdev = vlan_dev_real_dev(netdev);
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) {
|
||||
@@ -222,16 +140,14 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier,
|
||||
|
||||
if (!found)
|
||||
return NOTIFY_DONE;
|
||||
if (!rdma_link_local_addr((struct in6_addr *)&ifa->addr))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
mutex_lock(&dev->dev_lock);
|
||||
switch (event) {
|
||||
case NETDEV_UP:
|
||||
updated = ocrdma_add_sgid(dev, netdev->dev_addr, is_vlan, vid);
|
||||
updated = ocrdma_add_sgid(dev, gid);
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
updated = ocrdma_del_sgid(dev, netdev->dev_addr, is_vlan, vid);
|
||||
updated = ocrdma_del_sgid(dev, gid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -247,6 +163,32 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int ocrdma_inetaddr_event(struct notifier_block *notifier,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct in_ifaddr *ifa = ptr;
|
||||
union ib_gid gid;
|
||||
struct net_device *netdev = ifa->ifa_dev->dev;
|
||||
|
||||
ipv6_addr_set_v4mapped(ifa->ifa_address, (struct in6_addr *)&gid);
|
||||
return ocrdma_addr_event(event, netdev, &gid);
|
||||
}
|
||||
|
||||
static struct notifier_block ocrdma_inetaddr_notifier = {
|
||||
.notifier_call = ocrdma_inetaddr_event
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
||||
static int ocrdma_inet6addr_event(struct notifier_block *notifier,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
|
||||
union ib_gid *gid = (union ib_gid *)&ifa->addr;
|
||||
struct net_device *netdev = ifa->idev->dev;
|
||||
return ocrdma_addr_event(event, netdev, gid);
|
||||
}
|
||||
|
||||
static struct notifier_block ocrdma_inet6addr_notifier = {
|
||||
.notifier_call = ocrdma_inet6addr_event
|
||||
};
|
||||
@@ -423,10 +365,6 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
|
||||
if (status)
|
||||
goto alloc_err;
|
||||
|
||||
status = ocrdma_build_sgid_tbl(dev);
|
||||
if (status)
|
||||
goto alloc_err;
|
||||
|
||||
status = ocrdma_register_device(dev);
|
||||
if (status)
|
||||
goto alloc_err;
|
||||
@@ -553,6 +491,10 @@ static int __init ocrdma_init_module(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = register_inetaddr_notifier(&ocrdma_inetaddr_notifier);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
status = register_inet6addr_notifier(&ocrdma_inet6addr_notifier);
|
||||
if (status)
|
||||
|
@@ -1326,7 +1326,8 @@ int ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
new_qps = old_qps;
|
||||
spin_unlock_irqrestore(&qp->q_lock, flags);
|
||||
|
||||
if (!ib_modify_qp_is_ok(old_qps, new_qps, ibqp->qp_type, attr_mask)) {
|
||||
if (!ib_modify_qp_is_ok(old_qps, new_qps, ibqp->qp_type, attr_mask,
|
||||
IB_LINK_LAYER_ETHERNET)) {
|
||||
pr_err("%s(%d) invalid attribute mask=0x%x specified for\n"
|
||||
"qpn=0x%x of type=0x%x old_qps=0x%x, new_qps=0x%x\n",
|
||||
__func__, dev->id, attr_mask, qp->id, ibqp->qp_type,
|
||||
|
Reference in New Issue
Block a user