]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[hermon] Work around hardware stripping of VLAN tags
authorMichael Brown <mcb30@ipxe.org>
Wed, 1 Dec 2010 18:51:29 +0000 (18:51 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 1 Dec 2010 18:51:29 +0000 (18:51 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/infiniband/hermon.c
src/include/ipxe/infiniband.h

index 65b148cc277d00ff547777deb642ebe2d80d0ed2..63cf7d8cedbdd6bfc9dbc3a54c91babbed1dda89 100644 (file)
@@ -39,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/if_ether.h>
 #include <ipxe/ethernet.h>
 #include <ipxe/fcoe.h>
+#include <ipxe/vlan.h>
 #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 ) {
index be2b6e78db5c4fea9412af565d36531091ba2b38..f97a5d4fe2a47d7fcc8b620a4a016480d0898603 100644 (file)
@@ -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 */