[hermon] Work around hardware stripping of VLAN tags

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2010-12-01 18:51:29 +00:00
parent 5273c2748c
commit f14a5045d7
2 changed files with 21 additions and 3 deletions

View File

@@ -39,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/if_ether.h> #include <ipxe/if_ether.h>
#include <ipxe/ethernet.h> #include <ipxe/ethernet.h>
#include <ipxe/fcoe.h> #include <ipxe/fcoe.h>
#include <ipxe/vlan.h>
#include "hermon.h" #include "hermon.h"
/** /**
@@ -1648,6 +1649,7 @@ static int hermon_complete ( struct ib_device *ibdev,
len = MLX_GET ( &cqe->normal, byte_cnt ); len = MLX_GET ( &cqe->normal, byte_cnt );
assert ( len <= iob_tailroom ( iobuf ) ); assert ( len <= iob_tailroom ( iobuf ) );
iob_put ( iobuf, len ); iob_put ( iobuf, len );
memset ( &recv_av, 0, sizeof ( recv_av ) );
switch ( qp->type ) { switch ( qp->type ) {
case IB_QPT_SMI: case IB_QPT_SMI:
case IB_QPT_GSI: case IB_QPT_GSI:
@@ -1657,7 +1659,6 @@ static int hermon_complete ( struct ib_device *ibdev,
iob_pull ( iobuf, sizeof ( *grh ) ); iob_pull ( iobuf, sizeof ( *grh ) );
/* Construct address vector */ /* Construct address vector */
av = &recv_av; av = &recv_av;
memset ( av, 0, sizeof ( *av ) );
av->qpn = MLX_GET ( &cqe->normal, srq_rqpn ); av->qpn = MLX_GET ( &cqe->normal, srq_rqpn );
av->lid = MLX_GET ( &cqe->normal, slid_smac47_32 ); av->lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
av->sl = MLX_GET ( &cqe->normal, sl ); av->sl = MLX_GET ( &cqe->normal, sl );
@@ -1668,7 +1669,10 @@ static int hermon_complete ( struct ib_device *ibdev,
av = &qp->av; av = &qp->av;
break; break;
case IB_QPT_ETH: 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; break;
default: default:
assert ( 0 ); 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, static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_address_vector *av __unused, struct ib_address_vector *av,
struct io_buffer *iobuf, int rc ) { struct io_buffer *iobuf, int rc ) {
struct net_device *netdev = ib_qp_get_ownerdata ( qp ); 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 */ /* Hand off to network layer */
if ( rc == 0 ) { if ( rc == 0 ) {

View File

@@ -89,6 +89,10 @@ struct ib_address_vector {
unsigned int gid_present; unsigned int gid_present;
/** GID, if present */ /** GID, if present */
union ib_gid gid; union ib_gid gid;
/** VLAN is present */
unsigned int vlan_present;
/** VLAN, if present */
unsigned int vlan;
}; };
/** An Infiniband Work Queue */ /** An Infiniband Work Queue */