QUEUE_NB
};
-enum {
- /** Max number of pending rx packets */
- NUM_RX_BUF = 8,
-
- /** Max Ethernet frame length, including FCS and VLAN tag */
- RX_BUF_SIZE = 1522,
-};
+/** Max number of pending rx packets */
+#define NUM_RX_BUF 8
struct virtnet_nic {
/** Base pio register address */
*/
static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
struct virtnet_nic *virtnet = netdev->priv;
+ size_t len = ( netdev->max_pkt_len + 4 /* VLAN */ );
while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
struct io_buffer *iobuf;
/* Try to allocate a buffer, stop for now if out of memory */
- iobuf = alloc_iob ( RX_BUF_SIZE );
+ iobuf = alloc_iob ( len );
if ( ! iobuf )
break;
list_add ( &iobuf->list, &virtnet->rx_iobufs );
/* Mark packet length until we know the actual size */
- iob_put ( iobuf, RX_BUF_SIZE );
+ iob_put ( iobuf, len );
virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
virtnet->rx_num_iobufs++;
/* Driver is ready */
features = vp_get_features ( ioaddr );
- vp_set_features ( ioaddr, features & ( 1 << VIRTIO_NET_F_MAC ) );
+ vp_set_features ( ioaddr, features & ( ( 1 << VIRTIO_NET_F_MAC ) |
+ ( 1 << VIRTIO_NET_F_MTU ) ) );
vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
return 0;
}
}
vpm_set_features ( &virtnet->vdev, features & (
( 1ULL << VIRTIO_NET_F_MAC ) |
+ ( 1ULL << VIRTIO_NET_F_MTU ) |
( 1ULL << VIRTIO_F_VERSION_1 ) |
( 1ULL << VIRTIO_F_ANY_LAYOUT ) ) );
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK );
virtnet->rx_num_iobufs--;
/* Update iobuf length */
- iob_unput ( iobuf, RX_BUF_SIZE );
+ iob_unput ( iobuf, iob_len ( iobuf ) );
iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
DBGC2 ( virtnet, "VIRTIO-NET %p rx complete iobuf %p len %zd\n",
struct net_device *netdev;
struct virtnet_nic *virtnet;
u32 features;
+ u16 mtu;
int rc;
/* Allocate and hook up net device */
adjust_pci_device ( pci );
vp_reset ( ioaddr );
- /* Load MAC address */
+ /* Load MAC address and MTU */
features = vp_get_features ( ioaddr );
if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
eth_ntoa ( netdev->hw_addr ) );
}
+ if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
+ vp_get ( ioaddr, offsetof ( struct virtio_net_config, mtu ),
+ &mtu, sizeof ( mtu ) );
+ DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet, mtu );
+ netdev->max_pkt_len = ( mtu + ETH_HLEN );
+ }
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
struct net_device *netdev;
struct virtnet_nic *virtnet;
u64 features;
+ u16 mtu;
int rc, common, isr, notify, config, device;
common = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_COMMON_CFG );
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE );
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER );
- /* Load MAC address */
+ /* Load MAC address and MTU */
if ( device ) {
features = vpm_get_features ( &virtnet->vdev );
if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) {
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
eth_ntoa ( netdev->hw_addr ) );
}
+ if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
+ vpm_get ( &virtnet->vdev,
+ offsetof ( struct virtio_net_config, mtu ),
+ &mtu, sizeof ( mtu ) );
+ DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet,
+ mtu );
+ netdev->max_pkt_len = ( mtu + ETH_HLEN );
+ }
}
/* We need a valid MAC address */