From: Michael Brown Date: Wed, 1 Dec 2010 18:51:29 +0000 (+0000) Subject: [hermon] Work around hardware stripping of VLAN tags X-Git-Tag: v1.20.1~2364 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f14a5045d70fb0f46e8dec9bb2fe847407b0a278;p=thirdparty%2Fipxe.git [hermon] Work around hardware stripping of VLAN tags Signed-off-by: Michael Brown --- diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index 65b148cc2..63cf7d8ce 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -39,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include "hermon.h" /** @@ -1648,6 +1649,7 @@ static int hermon_complete ( struct ib_device *ibdev, len = MLX_GET ( &cqe->normal, byte_cnt ); assert ( len <= iob_tailroom ( iobuf ) ); iob_put ( iobuf, len ); + memset ( &recv_av, 0, sizeof ( recv_av ) ); switch ( qp->type ) { case IB_QPT_SMI: case IB_QPT_GSI: @@ -1657,7 +1659,6 @@ static int hermon_complete ( struct ib_device *ibdev, iob_pull ( iobuf, sizeof ( *grh ) ); /* Construct address vector */ av = &recv_av; - memset ( av, 0, sizeof ( *av ) ); av->qpn = MLX_GET ( &cqe->normal, srq_rqpn ); av->lid = MLX_GET ( &cqe->normal, slid_smac47_32 ); av->sl = MLX_GET ( &cqe->normal, sl ); @@ -1668,7 +1669,10 @@ static int hermon_complete ( struct ib_device *ibdev, av = &qp->av; break; case IB_QPT_ETH: - av = NULL; + /* Construct address vector */ + av = &recv_av; + av->vlan_present = MLX_GET ( &cqe->normal, vlan ); + av->vlan = MLX_GET ( &cqe->normal, vid ); break; default: assert ( 0 ); @@ -2275,9 +2279,19 @@ static void hermon_eth_complete_send ( struct ib_device *ibdev __unused, */ static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, - struct ib_address_vector *av __unused, + struct ib_address_vector *av, struct io_buffer *iobuf, int rc ) { struct net_device *netdev = ib_qp_get_ownerdata ( qp ); + struct net_device *vlan; + + /* Find VLAN device, if applicable */ + if ( av->vlan_present ) { + if ( ( vlan = vlan_find ( netdev, av->vlan ) ) != NULL ) { + netdev = vlan; + } else if ( rc == 0 ) { + rc = -ENODEV; + } + } /* Hand off to network layer */ if ( rc == 0 ) { diff --git a/src/include/ipxe/infiniband.h b/src/include/ipxe/infiniband.h index be2b6e78d..f97a5d4fe 100644 --- a/src/include/ipxe/infiniband.h +++ b/src/include/ipxe/infiniband.h @@ -89,6 +89,10 @@ struct ib_address_vector { unsigned int gid_present; /** GID, if present */ union ib_gid gid; + /** VLAN is present */ + unsigned int vlan_present; + /** VLAN, if present */ + unsigned int vlan; }; /** An Infiniband Work Queue */