[intelxl] Use VLAN tag in receive descriptor if present

The physical function driver does not allow the virtual function to
request that VLAN tags are left unstripped.  Extract and use the VLAN
tag from the receive descriptor if present.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/92/head
Michael Brown 2019-04-27 20:21:22 +01:00
parent fe680c8228
commit c901b5ca45
2 changed files with 19 additions and 3 deletions

View File

@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/netdevice.h> #include <ipxe/netdevice.h>
#include <ipxe/ethernet.h> #include <ipxe/ethernet.h>
#include <ipxe/if_ether.h> #include <ipxe/if_ether.h>
#include <ipxe/vlan.h>
#include <ipxe/iobuf.h> #include <ipxe/iobuf.h>
#include <ipxe/malloc.h> #include <ipxe/malloc.h>
#include <ipxe/pci.h> #include <ipxe/pci.h>
@ -1254,6 +1255,7 @@ static void intelxl_poll_rx ( struct net_device *netdev ) {
struct intelxl_rx_writeback_descriptor *rx_wb; struct intelxl_rx_writeback_descriptor *rx_wb;
struct io_buffer *iobuf; struct io_buffer *iobuf;
unsigned int rx_idx; unsigned int rx_idx;
unsigned int tag;
size_t len; size_t len;
/* Check for received packets */ /* Check for received packets */
@ -1273,16 +1275,23 @@ static void intelxl_poll_rx ( struct net_device *netdev ) {
len = INTELXL_RX_WB_LEN ( le32_to_cpu ( rx_wb->len ) ); len = INTELXL_RX_WB_LEN ( le32_to_cpu ( rx_wb->len ) );
iob_put ( iobuf, len ); iob_put ( iobuf, len );
/* Find VLAN device, if applicable */
if ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_VLAN ) ) {
tag = VLAN_TAG ( le16_to_cpu ( rx_wb->vlan ) );
} else {
tag = 0;
}
/* Hand off to network stack */ /* Hand off to network stack */
if ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_RXE ) ) { if ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_RXE ) ) {
DBGC ( intelxl, "INTELXL %p RX %d error (length %zd, " DBGC ( intelxl, "INTELXL %p RX %d error (length %zd, "
"flags %08x)\n", intelxl, rx_idx, len, "flags %08x)\n", intelxl, rx_idx, len,
le32_to_cpu ( rx_wb->flags ) ); le32_to_cpu ( rx_wb->flags ) );
netdev_rx_err ( netdev, iobuf, -EIO ); vlan_netdev_rx_err ( netdev, tag, iobuf, -EIO );
} else { } else {
DBGC2 ( intelxl, "INTELXL %p RX %d complete (length " DBGC2 ( intelxl, "INTELXL %p RX %d complete (length "
"%zd)\n", intelxl, rx_idx, len ); "%zd)\n", intelxl, rx_idx, len );
netdev_rx ( netdev, iobuf ); vlan_netdev_rx ( netdev, tag, iobuf );
} }
intelxl->rx.cons++; intelxl->rx.cons++;
} }

View File

@ -582,7 +582,11 @@ struct intelxl_rx_data_descriptor {
/** Receive writeback descriptor */ /** Receive writeback descriptor */
struct intelxl_rx_writeback_descriptor { struct intelxl_rx_writeback_descriptor {
/** Reserved */ /** Reserved */
uint8_t reserved[8]; uint8_t reserved_a[2];
/** VLAN tag */
uint16_t vlan;
/** Reserved */
uint8_t reserved_b[4];
/** Flags */ /** Flags */
uint32_t flags; uint32_t flags;
/** Length */ /** Length */
@ -592,6 +596,9 @@ struct intelxl_rx_writeback_descriptor {
/** Receive writeback descriptor complete */ /** Receive writeback descriptor complete */
#define INTELXL_RX_WB_FL_DD 0x00000001UL #define INTELXL_RX_WB_FL_DD 0x00000001UL
/** Receive writeback descriptor VLAN tag present */
#define INTELXL_RX_WB_FL_VLAN 0x00000004UL
/** Receive writeback descriptor error */ /** Receive writeback descriptor error */
#define INTELXL_RX_WB_FL_RXE 0x00080000UL #define INTELXL_RX_WB_FL_RXE 0x00080000UL