Commit dd5f03be authored by Matan Barak's avatar Matan Barak Committed by Roland Dreier

IB/core: Ethernet L2 attributes in verbs/cm structures

This patch add the support for Ethernet L2 attributes in the
verbs/cm/cma structures.

When dealing with L2 Ethernet, we should use smac, dmac, vlan ID and priority
in a similar manner that the IB L2 (and the L4 PKEY) attributes are used.

Thus, those attributes were added to the following structures:

* ib_ah_attr - added dmac
* ib_qp_attr - added smac and vlan_id, (sl remains vlan priority)
* ib_wc - added smac, vlan_id
* ib_sa_path_rec - added smac, dmac, vlan_id
* cm_av - added smac and vlan_id

For the path record structure, extra care was taken to avoid the new
fields when packing it into wire format, so we don't break the IB CM
and SA wire protocol.

On the active side, the CM fills. its internal structures from the
path provided by the ULP.  We add there taking the ETH L2 attributes
and placing them into the CM Address Handle (struct cm_av).

On the passive side, the CM fills its internal structures from the WC
associated with the REQ message.  We add there taking the ETH L2
attributes from the WC.

When the HW driver provides the required ETH L2 attributes in the WC,
they set the IB_WC_WITH_SMAC and IB_WC_WITH_VLAN flags. The IB core
code checks for the presence of these flags, and in their absence does
address resolution from the ib_init_ah_from_wc() helper function.

ib_modify_qp_is_ok is also updated to consider the link layer. Some
parameters are mandatory for Ethernet link layer, while they are
irrelevant for IB.  Vendor drivers are modified to support the new
function signature.
Signed-off-by: default avatarMatan Barak <matanb@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 7e22e911
...@@ -86,6 +86,8 @@ int rdma_addr_size(struct sockaddr *addr) ...@@ -86,6 +86,8 @@ int rdma_addr_size(struct sockaddr *addr)
} }
EXPORT_SYMBOL(rdma_addr_size); EXPORT_SYMBOL(rdma_addr_size);
static struct rdma_addr_client self;
void rdma_addr_register_client(struct rdma_addr_client *client) void rdma_addr_register_client(struct rdma_addr_client *client)
{ {
atomic_set(&client->refcount, 1); atomic_set(&client->refcount, 1);
...@@ -119,7 +121,8 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, ...@@ -119,7 +121,8 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
} }
EXPORT_SYMBOL(rdma_copy_addr); EXPORT_SYMBOL(rdma_copy_addr);
int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
u16 *vlan_id)
{ {
struct net_device *dev; struct net_device *dev;
int ret = -EADDRNOTAVAIL; int ret = -EADDRNOTAVAIL;
...@@ -142,6 +145,8 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) ...@@ -142,6 +145,8 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
return ret; return ret;
ret = rdma_copy_addr(dev_addr, dev, NULL); ret = rdma_copy_addr(dev_addr, dev, NULL);
if (vlan_id)
*vlan_id = rdma_vlan_dev_vlan_id(dev);
dev_put(dev); dev_put(dev);
break; break;
...@@ -153,6 +158,8 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) ...@@ -153,6 +158,8 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
&((struct sockaddr_in6 *) addr)->sin6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
dev, 1)) { dev, 1)) {
ret = rdma_copy_addr(dev_addr, dev, NULL); ret = rdma_copy_addr(dev_addr, dev, NULL);
if (vlan_id)
*vlan_id = rdma_vlan_dev_vlan_id(dev);
break; break;
} }
} }
...@@ -238,7 +245,7 @@ static int addr4_resolve(struct sockaddr_in *src_in, ...@@ -238,7 +245,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
src_in->sin_addr.s_addr = fl4.saddr; src_in->sin_addr.s_addr = fl4.saddr;
if (rt->dst.dev->flags & IFF_LOOPBACK) { if (rt->dst.dev->flags & IFF_LOOPBACK) {
ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); ret = rdma_translate_ip((struct sockaddr *)dst_in, addr, NULL);
if (!ret) if (!ret)
memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
goto put; goto put;
...@@ -286,7 +293,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, ...@@ -286,7 +293,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
} }
if (dst->dev->flags & IFF_LOOPBACK) { if (dst->dev->flags & IFF_LOOPBACK) {
ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); ret = rdma_translate_ip((struct sockaddr *)dst_in, addr, NULL);
if (!ret) if (!ret)
memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
goto put; goto put;
...@@ -437,6 +444,88 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr) ...@@ -437,6 +444,88 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
} }
EXPORT_SYMBOL(rdma_addr_cancel); EXPORT_SYMBOL(rdma_addr_cancel);
struct resolve_cb_context {
struct rdma_dev_addr *addr;
struct completion comp;
};
static void resolve_cb(int status, struct sockaddr *src_addr,
struct rdma_dev_addr *addr, void *context)
{
memcpy(((struct resolve_cb_context *)context)->addr, addr, sizeof(struct
rdma_dev_addr));
complete(&((struct resolve_cb_context *)context)->comp);
}
int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *dmac,
u16 *vlan_id)
{
int ret = 0;
struct rdma_dev_addr dev_addr;
struct resolve_cb_context ctx;
struct net_device *dev;
union {
struct sockaddr _sockaddr;
struct sockaddr_in _sockaddr_in;
struct sockaddr_in6 _sockaddr_in6;
} sgid_addr, dgid_addr;
ret = rdma_gid2ip(&sgid_addr._sockaddr, sgid);
if (ret)
return ret;
ret = rdma_gid2ip(&dgid_addr._sockaddr, dgid);
if (ret)
return ret;
memset(&dev_addr, 0, sizeof(dev_addr));
ctx.addr = &dev_addr;
init_completion(&ctx.comp);
ret = rdma_resolve_ip(&self, &sgid_addr._sockaddr, &dgid_addr._sockaddr,
&dev_addr, 1000, resolve_cb, &ctx);
if (ret)
return ret;
wait_for_completion(&ctx.comp);
memcpy(dmac, dev_addr.dst_dev_addr, ETH_ALEN);
dev = dev_get_by_index(&init_net, dev_addr.bound_dev_if);
if (!dev)
return -ENODEV;
if (vlan_id)
*vlan_id = rdma_vlan_dev_vlan_id(dev);
dev_put(dev);
return ret;
}
EXPORT_SYMBOL(rdma_addr_find_dmac_by_grh);
int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id)
{
int ret = 0;
struct rdma_dev_addr dev_addr;
union {
struct sockaddr _sockaddr;
struct sockaddr_in _sockaddr_in;
struct sockaddr_in6 _sockaddr_in6;
} gid_addr;
ret = rdma_gid2ip(&gid_addr._sockaddr, sgid);
if (ret)
return ret;
memset(&dev_addr, 0, sizeof(dev_addr));
ret = rdma_translate_ip(&gid_addr._sockaddr, &dev_addr, vlan_id);
if (ret)
return ret;
memcpy(smac, dev_addr.src_dev_addr, ETH_ALEN);
return ret;
}
EXPORT_SYMBOL(rdma_addr_find_smac_by_sgid);
static int netevent_callback(struct notifier_block *self, unsigned long event, static int netevent_callback(struct notifier_block *self, unsigned long event,
void *ctx) void *ctx)
{ {
...@@ -461,11 +550,13 @@ static int __init addr_init(void) ...@@ -461,11 +550,13 @@ static int __init addr_init(void)
return -ENOMEM; return -ENOMEM;
register_netevent_notifier(&nb); register_netevent_notifier(&nb);
rdma_addr_register_client(&self);
return 0; return 0;
} }
static void __exit addr_cleanup(void) static void __exit addr_cleanup(void)
{ {
rdma_addr_unregister_client(&self);
unregister_netevent_notifier(&nb); unregister_netevent_notifier(&nb);
destroy_workqueue(addr_wq); destroy_workqueue(addr_wq);
} }
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/etherdevice.h>
#include <rdma/ib_cache.h> #include <rdma/ib_cache.h>
#include <rdma/ib_cm.h> #include <rdma/ib_cm.h>
...@@ -177,6 +178,8 @@ struct cm_av { ...@@ -177,6 +178,8 @@ struct cm_av {
struct ib_ah_attr ah_attr; struct ib_ah_attr ah_attr;
u16 pkey_index; u16 pkey_index;
u8 timeout; u8 timeout;
u8 valid;
u8 smac[ETH_ALEN];
}; };
struct cm_work { struct cm_work {
...@@ -346,6 +349,23 @@ static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc, ...@@ -346,6 +349,23 @@ static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
grh, &av->ah_attr); grh, &av->ah_attr);
} }
int ib_update_cm_av(struct ib_cm_id *id, const u8 *smac, const u8 *alt_smac)
{
struct cm_id_private *cm_id_priv;
cm_id_priv = container_of(id, struct cm_id_private, id);
if (smac != NULL)
memcpy(cm_id_priv->av.smac, smac, sizeof(cm_id_priv->av.smac));
if (alt_smac != NULL)
memcpy(cm_id_priv->alt_av.smac, alt_smac,
sizeof(cm_id_priv->alt_av.smac));
return 0;
}
EXPORT_SYMBOL(ib_update_cm_av);
static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
{ {
struct cm_device *cm_dev; struct cm_device *cm_dev;
...@@ -376,6 +396,9 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) ...@@ -376,6 +396,9 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path, ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path,
&av->ah_attr); &av->ah_attr);
av->timeout = path->packet_life_time + 1; av->timeout = path->packet_life_time + 1;
memcpy(av->smac, path->smac, sizeof(av->smac));
av->valid = 1;
return 0; return 0;
} }
...@@ -1554,6 +1577,9 @@ static int cm_req_handler(struct cm_work *work) ...@@ -1554,6 +1577,9 @@ static int cm_req_handler(struct cm_work *work)
cm_process_routed_req(req_msg, work->mad_recv_wc->wc); cm_process_routed_req(req_msg, work->mad_recv_wc->wc);
cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]); cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
memcpy(work->path[0].dmac, cm_id_priv->av.ah_attr.dmac, ETH_ALEN);
work->path[0].vlan_id = cm_id_priv->av.ah_attr.vlan_id;
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av); ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
if (ret) { if (ret) {
ib_get_cached_gid(work->port->cm_dev->ib_device, ib_get_cached_gid(work->port->cm_dev->ib_device,
...@@ -3500,6 +3526,30 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv, ...@@ -3500,6 +3526,30 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
*qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU | *qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU |
IB_QP_DEST_QPN | IB_QP_RQ_PSN; IB_QP_DEST_QPN | IB_QP_RQ_PSN;
qp_attr->ah_attr = cm_id_priv->av.ah_attr; qp_attr->ah_attr = cm_id_priv->av.ah_attr;
if (!cm_id_priv->av.valid)
return -EINVAL;
if (cm_id_priv->av.ah_attr.vlan_id != 0xffff) {
qp_attr->vlan_id = cm_id_priv->av.ah_attr.vlan_id;
*qp_attr_mask |= IB_QP_VID;
}
if (!is_zero_ether_addr(cm_id_priv->av.smac)) {
memcpy(qp_attr->smac, cm_id_priv->av.smac,
sizeof(qp_attr->smac));
*qp_attr_mask |= IB_QP_SMAC;
}
if (cm_id_priv->alt_av.valid) {
if (cm_id_priv->alt_av.ah_attr.vlan_id != 0xffff) {
qp_attr->alt_vlan_id =
cm_id_priv->alt_av.ah_attr.vlan_id;
*qp_attr_mask |= IB_QP_ALT_VID;
}
if (!is_zero_ether_addr(cm_id_priv->alt_av.smac)) {
memcpy(qp_attr->alt_smac,
cm_id_priv->alt_av.smac,
sizeof(qp_attr->alt_smac));
*qp_attr_mask |= IB_QP_ALT_SMAC;
}
}
qp_attr->path_mtu = cm_id_priv->path_mtu; qp_attr->path_mtu = cm_id_priv->path_mtu;
qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn); qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn); qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
......
...@@ -340,7 +340,7 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a ...@@ -340,7 +340,7 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a
int ret; int ret;
if (addr->sa_family != AF_IB) { if (addr->sa_family != AF_IB) {
ret = rdma_translate_ip(addr, dev_addr); ret = rdma_translate_ip(addr, dev_addr, NULL);
} else { } else {
cma_translate_ib((struct sockaddr_ib *) addr, dev_addr); cma_translate_ib((struct sockaddr_ib *) addr, dev_addr);
ret = 0; ret = 0;
...@@ -603,6 +603,7 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv, ...@@ -603,6 +603,7 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
{ {
struct ib_qp_attr qp_attr; struct ib_qp_attr qp_attr;
int qp_attr_mask, ret; int qp_attr_mask, ret;
union ib_gid sgid;
mutex_lock(&id_priv->qp_mutex); mutex_lock(&id_priv->qp_mutex);
if (!id_priv->id.qp) { if (!id_priv->id.qp) {
...@@ -625,6 +626,20 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv, ...@@ -625,6 +626,20 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
if (ret) if (ret)
goto out; goto out;
ret = ib_query_gid(id_priv->id.device, id_priv->id.port_num,
qp_attr.ah_attr.grh.sgid_index, &sgid);
if (ret)
goto out;
if (rdma_node_get_transport(id_priv->cma_dev->device->node_type)
== RDMA_TRANSPORT_IB &&
rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)
== IB_LINK_LAYER_ETHERNET) {
ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL);
if (ret)
goto out;
}
if (conn_param) if (conn_param)
qp_attr.max_dest_rd_atomic = conn_param->responder_resources; qp_attr.max_dest_rd_atomic = conn_param->responder_resources;
ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask); ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
...@@ -725,6 +740,7 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, ...@@ -725,6 +740,7 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
else else
ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr, ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
qp_attr_mask); qp_attr_mask);
if (qp_attr->qp_state == IB_QPS_RTR) if (qp_attr->qp_state == IB_QPS_RTR)
qp_attr->rq_psn = id_priv->seq_num; qp_attr->rq_psn = id_priv->seq_num;
break; break;
...@@ -1266,6 +1282,15 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) ...@@ -1266,6 +1282,15 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
struct rdma_id_private *listen_id, *conn_id; struct rdma_id_private *listen_id, *conn_id;
struct rdma_cm_event event; struct rdma_cm_event event;
int offset, ret; int offset, ret;
u8 smac[ETH_ALEN];
u8 alt_smac[ETH_ALEN];
u8 *psmac = smac;
u8 *palt_smac = alt_smac;
int is_iboe = ((rdma_node_get_transport(cm_id->device->node_type) ==
RDMA_TRANSPORT_IB) &&
(rdma_port_get_link_layer(cm_id->device,
ib_event->param.req_rcvd.port) ==
IB_LINK_LAYER_ETHERNET));
listen_id = cm_id->context; listen_id = cm_id->context;
if (!cma_check_req_qp_type(&listen_id->id, ib_event)) if (!cma_check_req_qp_type(&listen_id->id, ib_event))
...@@ -1310,12 +1335,29 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) ...@@ -1310,12 +1335,29 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
if (ret) if (ret)
goto err3; goto err3;
if (is_iboe) {
if (ib_event->param.req_rcvd.primary_path != NULL)
rdma_addr_find_smac_by_sgid(
&ib_event->param.req_rcvd.primary_path->sgid,
psmac, NULL);
else
psmac = NULL;
if (ib_event->param.req_rcvd.alternate_path != NULL)
rdma_addr_find_smac_by_sgid(
&ib_event->param.req_rcvd.alternate_path->sgid,
palt_smac, NULL);
else
palt_smac = NULL;
}
/* /*
* Acquire mutex to prevent user executing rdma_destroy_id() * Acquire mutex to prevent user executing rdma_destroy_id()
* while we're accessing the cm_id. * while we're accessing the cm_id.
*/ */
mutex_lock(&lock); mutex_lock(&lock);
if (cma_comp(conn_id, RDMA_CM_CONNECT) && (conn_id->id.qp_type != IB_QPT_UD)) if (is_iboe)
ib_update_cm_av(cm_id, psmac, palt_smac);
if (cma_comp(conn_id, RDMA_CM_CONNECT) &&
(conn_id->id.qp_type != IB_QPT_UD))
ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
mutex_unlock(&lock); mutex_unlock(&lock);
mutex_unlock(&conn_id->handler_mutex); mutex_unlock(&conn_id->handler_mutex);
...@@ -1474,7 +1516,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, ...@@ -1474,7 +1516,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING); mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
conn_id->state = RDMA_CM_CONNECT; conn_id->state = RDMA_CM_CONNECT;
ret = rdma_translate_ip(laddr, &conn_id->id.route.addr.dev_addr); ret = rdma_translate_ip(laddr, &conn_id->id.route.addr.dev_addr, NULL);
if (ret) { if (ret) {
mutex_unlock(&conn_id->handler_mutex); mutex_unlock(&conn_id->handler_mutex);
rdma_destroy_id(new_cm_id); rdma_destroy_id(new_cm_id);
...@@ -1873,7 +1915,7 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) ...@@ -1873,7 +1915,7 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
struct cma_work *work; struct cma_work *work;
int ret; int ret;
struct net_device *ndev = NULL; struct net_device *ndev = NULL;
u16 vid;
work = kzalloc(sizeof *work, GFP_KERNEL); work = kzalloc(sizeof *work, GFP_KERNEL);
if (!work) if (!work)
...@@ -1897,10 +1939,14 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) ...@@ -1897,10 +1939,14 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
goto err2; goto err2;
} }
vid = rdma_vlan_dev_vlan_id(ndev); route->path_rec->vlan_id = rdma_vlan_dev_vlan_id(ndev);
memcpy(route->path_rec->dmac, addr->dev_addr.dst_dev_addr, ETH_ALEN);
memcpy(route->path_rec->smac, ndev->dev_addr, ndev->addr_len);
iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr, vid); iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr,
iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr, vid); route->path_rec->vlan_id);
iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr,
route->path_rec->vlan_id);
route->path_rec->hop_limit = 1; route->path_rec->hop_limit = 1;
route->path_rec->reversible = 1; route->path_rec->reversible = 1;
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <uapi/linux/if_ether.h>
#include <rdma/ib_pack.h> #include <rdma/ib_pack.h>
#include <rdma/ib_cache.h> #include <rdma/ib_cache.h>
#include "sa.h" #include "sa.h"
...@@ -556,6 +556,13 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num, ...@@ -556,6 +556,13 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
ah_attr->grh.hop_limit = rec->hop_limit; ah_attr->grh.hop_limit = rec->hop_limit;
ah_attr->grh.traffic_class = rec->traffic_class; ah_attr->grh.traffic_class = rec->traffic_class;
} }
if (force_grh) {
memcpy(ah_attr->dmac, rec->dmac, ETH_ALEN);
ah_attr->vlan_id = rec->vlan_id;
} else {
ah_attr->vlan_id = 0xffff;
}
return 0; return 0;
} }
EXPORT_SYMBOL(ib_init_ah_from_path); EXPORT_SYMBOL(ib_init_ah_from_path);
...@@ -670,6 +677,9 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, ...@@ -670,6 +677,9 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),
mad->data, &rec); mad->data, &rec);
rec.vlan_id = 0xffff;
memset(rec.dmac, 0, ETH_ALEN);
memset(rec.smac, 0, ETH_ALEN);
query->callback(status, &rec, query->context); query->callback(status, &rec, query->context);
} else } else
query->callback(status, NULL, query->context); query->callback(status, NULL, query->context);
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h> #include <rdma/ib_cache.h>
#include <rdma/ib_addr.h>
int ib_rate_to_mult(enum ib_rate rate) int ib_rate_to_mult(enum ib_rate rate)
{ {
...@@ -192,8 +193,28 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, ...@@ -192,8 +193,28 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
u32 flow_class; u32 flow_class;
u16 gid_index; u16 gid_index;
int ret; int ret;
int is_eth = (rdma_port_get_link_layer(device, port_num) ==
IB_LINK_LAYER_ETHERNET);
memset(ah_attr, 0, sizeof *ah_attr); memset(ah_attr, 0, sizeof *ah_attr);
if (is_eth) {
if (!(wc->wc_flags & IB_WC_GRH))
return -EPROTOTYPE;
if (wc->wc_flags & IB_WC_WITH_SMAC &&
wc->wc_flags & IB_WC_WITH_VLAN) {
memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
ah_attr->vlan_id = wc->vlan_id;
} else {
ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
ah_attr->dmac, &ah_attr->vlan_id);
if (ret)
return ret;
}
} else {
ah_attr->vlan_id = 0xffff;
}
ah_attr->dlid = wc->slid; ah_attr->dlid = wc->slid;
ah_attr->sl = wc->sl; ah_attr->sl = wc->sl;
ah_attr->src_path_bits = wc->dlid_path_bits; ah_attr->src_path_bits = wc->dlid_path_bits;
...@@ -476,7 +497,9 @@ EXPORT_SYMBOL(ib_create_qp); ...@@ -476,7 +497,9 @@ EXPORT_SYMBOL(ib_create_qp);
static const struct { static const struct {
int valid; int valid;
enum ib_qp_attr_mask req_param[IB_QPT_MAX]; enum ib_qp_attr_mask req_param[IB_QPT_MAX];
enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX];
enum ib_qp_attr_mask opt_param[IB_QPT_MAX]; enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX];
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = { [IB_QPS_RESET] = {
[IB_QPS_RESET] = { .valid = 1 }, [IB_QPS_RESET] = { .valid = 1 },
...@@ -557,6 +580,12 @@ static const struct { ...@@ -557,6 +580,12 @@ static const struct {
IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER), IB_QP_MIN_RNR_TIMER),
}, },
.req_param_add_eth = {
[IB_QPT_RC] = (IB_QP_SMAC),
[IB_QPT_UC] = (IB_QP_SMAC),
[IB_QPT_XRC_INI] = (IB_QP_SMAC),
[IB_QPT_XRC_TGT] = (IB_QP_SMAC)
},
.opt_param = { .opt_param = {
[IB_QPT_UD] = (IB_QP_PKEY_INDEX | [IB_QPT_UD] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY), IB_QP_QKEY),
...@@ -576,7 +605,21 @@ static const struct { ...@@ -576,7 +605,21 @@ static const struct {
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY), IB_QP_QKEY),
} },
.opt_param_add_eth = {
[IB_QPT_RC] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID),
[IB_QPT_UC] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID),
[IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID),
[IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID)
}
} }
}, },
[IB_QPS_RTR] = { [IB_QPS_RTR] = {
...@@ -779,7 +822,8 @@ static const struct { ...@@ -779,7 +822,8 @@ static const struct {
}; };
int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
enum ib_qp_type type, enum ib_qp_attr_mask mask) enum ib_qp_type type, enum ib_qp_attr_mask mask,
enum rdma_link_layer ll)
{ {
enum ib_qp_attr_mask req_param, opt_param; enum ib_qp_attr_mask req_param, opt_param;
...@@ -798,6 +842,13 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, ...@@ -798,6 +842,13 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
req_param = qp_state_table[cur_state][next_state].req_param[type]; req_param = qp_state_table[cur_state][next_state].req_param[type];
opt_param = qp_state_table[cur_state][next_state].opt_param[type]; opt_param = qp_state_table[cur_state][next_state].opt_param[type];
if (ll == IB_LINK_LAYER_ETHERNET) {
req_param |= qp_state_table[cur_state][next_state].
req_param_add_eth[type];
opt_param |= qp_state_table[cur_state][next_state].
opt_param_add_eth[type];
}
if ((mask & req_param) != req_param) if ((mask & req_param) != req_param)
return 0; return 0;
......
...@@ -1329,7 +1329,7 @@ static int internal_modify_qp(struct ib_qp *ibqp, ...@@ -1329,7 +1329,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state; qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state;
if (!smi_reset2init && if (!smi_reset2init &&
!ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type, !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type,
attr_mask)) { attr_mask, IB_LINK_LAYER_UNSPECIFIED)) {
ret = -EINVAL; ret = -EINVAL;
ehca_err(ibqp->device, ehca_err(ibqp->device,
"Invalid qp transition new_state=%x cur_state=%x " "Invalid qp transition new_state=%x cur_state=%x "
......
...@@ -463,7 +463,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, ...@@ -463,7 +463,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
attr_mask)) attr_mask, IB_LINK_LAYER_UNSPECIFIED))
goto inval; goto inval;
if (attr_mask & IB_QP_AV) { if (attr_mask & IB_QP_AV) {
......
...@@ -1561,13 +1561,18 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, ...@@ -1561,13 +1561,18 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
struct mlx4_ib_qp *qp = to_mqp(ibqp); struct mlx4_ib_qp *qp = to_mqp(ibqp);
enum ib_qp_state cur_state, new_state; enum ib_qp_state cur_state, new_state;
int err = -EINVAL; int err = -EINVAL;
int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
mutex_lock(&qp->mutex); mutex_lock(&qp->mutex);
cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) { if (cur_state == new_state && cur_state == IB_QPS_RESET)
p = IB_LINK_LAYER_UNSPECIFIED;
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
attr_mask,
rdma_port_get_link_layer(&dev->ib_dev, p))) {
pr_debug("qpn 0x%x: invalid attribute mask specified " pr_debug("qpn 0x%x: invalid attribute mask specified "
"for transition %d to %d. qp_type %d," "for transition %d to %d. qp_type %d,"
" attr_mask 0x%x\n", " attr_mask 0x%x\n",
......
...@@ -1616,7 +1616,8 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, ...@@ -1616,7 +1616,8 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
if (ibqp->qp_type != MLX5_IB_QPT_REG_UMR && if (ibqp->qp_type != MLX5_IB_QPT_REG_UMR &&
!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) !ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask,
IB_LINK_LAYER_UNSPECIFIED))
goto out; goto out;
if ((attr_mask & IB_QP_PORT) && if ((attr_mask & IB_QP_PORT) &&
......
...@@ -860,7 +860,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, ...@@ -860,7 +860,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) { if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask,
IB_LINK_LAYER_UNSPECIFIED)) {
mthca_dbg(dev, "Bad QP transition (transport %d) " mthca_dbg(dev, "Bad QP transition (transport %d) "
"%d->%d with attr 0x%08x\n", "%d->%d with attr 0x%08x\n",
qp->transport, cur_state, new_state, qp->transport, cur_state, new_state,
......
...@@ -1326,7 +1326,8 @@ int ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, ...@@ -1326,7 +1326,8 @@ int ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
new_qps = old_qps; new_qps = old_qps;
spin_unlock_irqrestore(&qp->q_lock, flags); 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_UNSPECIFIED)) {
pr_err("%s(%d) invalid attribute mask=0x%x specified for\n" 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", "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, __func__, dev->id, attr_mask, qp->id, ibqp->qp_type,
......
...@@ -585,7 +585,7 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, ...@@ -585,7 +585,7 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
attr_mask)) attr_mask, IB_LINK_LAYER_UNSPECIFIED))
goto inval; goto inval;
if (attr_mask & IB_QP_AV) { if (attr_mask & IB_QP_AV) {
......
...@@ -1095,6 +1095,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, ...@@ -1095,6 +1095,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc); int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc);
int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw, int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
u8 *pg, u16 *ratelimit); u8 *pg, u16 *ratelimit);
int mlx4_find_cached_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *idx);
int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan); void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h> #include <rdma/ib_pack.h>
#include <net/ipv6.h>
struct rdma_addr_client { struct rdma_addr_client {
atomic_t refcount; atomic_t refcount;
...@@ -72,7 +73,8 @@ struct rdma_dev_addr { ...@@ -72,7 +73,8 @@ struct rdma_dev_addr {
* rdma_translate_ip - Translate a local IP address to an RDMA hardware * rdma_translate_ip - Translate a local IP address to an RDMA hardware
* address. * address.
*/ */
int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr); int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
u16 *vlan_id);
/** /**
* rdma_resolve_ip - Resolve source and destination IP addresses to * rdma_resolve_ip - Resolve source and destination IP addresses to
...@@ -104,6 +106,10 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, ...@@ -104,6 +106,10 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
int rdma_addr_size(struct sockaddr *addr); int rdma_addr_size(struct sockaddr *addr);
int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id);
int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *smac,
u16 *vlan_id);
static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr) 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]; return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9];
...@@ -142,6 +148,40 @@ static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid) ...@@ -142,6 +148,40 @@ static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid)
gid->raw[8] ^= 2; gid->raw[8] ^= 2;
} }
static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid)
{
switch (addr->sa_family) {
case AF_INET:
ipv6_addr_set_v4mapped(((struct sockaddr_in *)
addr)->sin_addr.s_addr,
(struct in6_addr *)gid);
break;
case AF_INET6:
memcpy(gid->raw, &((struct sockaddr_in6 *)addr)->sin6_addr, 16);
break;
default:
return -EINVAL;
}
return 0;
}
/* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */
static inline int rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
{
if (ipv6_addr_v4mapped((struct in6_addr *)gid)) {
struct sockaddr_in *out_in = (struct sockaddr_in *)out;
memset(out_in, 0, sizeof(*out_in));
out_in->sin_family = AF_INET;
memcpy(&out_in->sin_addr.s_addr, gid->raw + 12, 4);
} else {
struct sockaddr_in6 *out_in = (struct sockaddr_in6 *)out;
memset(out_in, 0, sizeof(*out_in));
out_in->sin6_family = AF_INET6;
memcpy(&out_in->sin6_addr.s6_addr, gid->raw, 16);
}
return 0;
}
static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev) static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
{ {
return dev->priv_flags & IFF_802_1Q_VLAN ? return dev->priv_flags & IFF_802_1Q_VLAN ?
......
...@@ -601,4 +601,5 @@ struct ib_cm_sidr_rep_param { ...@@ -601,4 +601,5 @@ struct ib_cm_sidr_rep_param {
int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id, int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
struct ib_cm_sidr_rep_param *param); struct ib_cm_sidr_rep_param *param);
int ib_update_cm_av(struct ib_cm_id *id, const u8 *smac, const u8 *alt_smac);
#endif /* IB_CM_H */ #endif /* IB_CM_H */
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define IB_PACK_H #define IB_PACK_H
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <uapi/linux/if_ether.h>
enum { enum {
IB_LRH_BYTES = 8, IB_LRH_BYTES = 8,
......
...@@ -154,6 +154,9 @@ struct ib_sa_path_rec { ...@@ -154,6 +154,9 @@ struct ib_sa_path_rec {
u8 packet_life_time_selector; u8 packet_life_time_selector;
u8 packet_life_time; u8 packet_life_time;
u8 preference; u8 preference;
u8 smac[ETH_ALEN];
u8 dmac[ETH_ALEN];
u16 vlan_id;
}; };
#define IB_SA_MCMEMBER_REC_MGID IB_SA_COMP_MASK( 0) #define IB_SA_MCMEMBER_REC_MGID IB_SA_COMP_MASK( 0)
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <uapi/linux/if_ether.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -472,6 +473,8 @@ struct ib_ah_attr { ...@@ -472,6 +473,8 @@ struct ib_ah_attr {
u8 static_rate; u8 static_rate;
u8 ah_flags; u8 ah_flags;
u8 port_num; u8 port_num;
u8 dmac[ETH_ALEN];
u16 vlan_id;
}; };
enum ib_wc_status { enum ib_wc_status {
...@@ -524,6 +527,8 @@ enum ib_wc_flags { ...@@ -524,6 +527,8 @@ enum ib_wc_flags {
IB_WC_WITH_IMM = (1<<1), IB_WC_WITH_IMM = (1<<1),
IB_WC_WITH_INVALIDATE = (1<<2), IB_WC_WITH_INVALIDATE = (1<<2),
IB_WC_IP_CSUM_OK = (1<<3), IB_WC_IP_CSUM_OK = (1<<3),
IB_WC_WITH_SMAC = (1<<4),
IB_WC_WITH_VLAN = (1<<5),
}; };
struct ib_wc { struct ib_wc {
...@@ -544,6 +549,8 @@ struct ib_wc { ...@@ -544,6 +549,8 @@ struct ib_wc {
u8 sl; u8 sl;
u8 dlid_path_bits; u8 dlid_path_bits;
u8 port_num; /* valid only for DR SMPs on switches */ u8 port_num; /* valid only for DR SMPs on switches */
u8 smac[ETH_ALEN];
u16 vlan_id;
}; };
enum ib_cq_notify_flags { enum ib_cq_notify_flags {
...@@ -721,7 +728,11 @@ enum ib_qp_attr_mask { ...@@ -721,7 +728,11 @@ enum ib_qp_attr_mask {
IB_QP_MAX_DEST_RD_ATOMIC = (1<<17), IB_QP_MAX_DEST_RD_ATOMIC = (1<<17),
IB_QP_PATH_MIG_STATE = (1<<18), IB_QP_PATH_MIG_STATE = (1<<18),
IB_QP_CAP = (1<<19), IB_QP_CAP = (1<<19),
IB_QP_DEST_QPN = (1<<20) IB_QP_DEST_QPN = (1<<20),
IB_QP_SMAC = (1<<21),
IB_QP_ALT_SMAC = (1<<22),
IB_QP_VID = (1<<23),
IB_QP_ALT_VID = (1<<24),
}; };
enum ib_qp_state { enum ib_qp_state {
...@@ -771,6 +782,10 @@ struct ib_qp_attr { ...@@ -771,6 +782,10 @@ struct ib_qp_attr {
u8 rnr_retry; u8 rnr_retry;
u8 alt_port_num; u8 alt_port_num;
u8 alt_timeout; u8 alt_timeout;
u8 smac[ETH_ALEN];
u8 alt_smac[ETH_ALEN];
u16 vlan_id;
u16 alt_vlan_id;
}; };
enum ib_wr_opcode { enum ib_wr_opcode {
...@@ -1488,6 +1503,7 @@ static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len ...@@ -1488,6 +1503,7 @@ static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len
* @next_state: Next QP state * @next_state: Next QP state
* @type: QP type * @type: QP type
* @mask: Mask of supplied QP attributes * @mask: Mask of supplied QP attributes
* @ll : link layer of port
* *
* This function is a helper function that a low-level driver's * This function is a helper function that a low-level driver's
* modify_qp method can use to validate the consumer's input. It * modify_qp method can use to validate the consumer's input. It
...@@ -1496,7 +1512,8 @@ static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len ...@@ -1496,7 +1512,8 @@ static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len
* and that the attribute mask supplied is allowed for the transition. * and that the attribute mask supplied is allowed for the transition.
*/ */
int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
enum ib_qp_type type, enum ib_qp_attr_mask mask); enum ib_qp_type type, enum ib_qp_attr_mask mask,
enum rdma_link_layer ll);
int ib_register_event_handler (struct ib_event_handler *event_handler); int ib_register_event_handler (struct ib_event_handler *event_handler);
int ib_unregister_event_handler(struct ib_event_handler *event_handler); int ib_unregister_event_handler(struct ib_event_handler *event_handler);
......
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