8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * This file and its contents are supplied under the terms of the
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Common Development and Distribution License ("CDDL"), version 1.0.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * You may only use this file in accordance with the terms of version
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * 1.0 of the CDDL.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * A full copy of the text of the CDDL should have accompanied this
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * source. A copy of the CDDL is also available via the Internet at
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * http://www.illumos.org/license/CDDL.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Copyright 2013 Nexenta Inc. All rights reserved.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * Copyright (c) 2014, 2016 by Delphix. All rights reserved.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Based on the NetBSD virtio driver by Minoura Makoto. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Copyright (c) 2010 Minoura Makoto.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * All rights reserved.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Redistribution and use in source and binary forms, with or without
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * modification, are permitted provided that the following conditions
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * are met:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * 1. Redistributions of source code must retain the above copyright
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * notice, this list of conditions and the following disclaimer.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * 2. Redistributions in binary form must reproduce the above copyright
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * notice, this list of conditions and the following disclaimer in the
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * documentation and/or other materials provided with the distribution.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/types.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/errno.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/param.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/stropts.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/stream.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/strsubr.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/kmem.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/conf.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/devops.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/ksynch.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/stat.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/modctl.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/debug.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/pci.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/ethernet.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/vlan.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/dlpi.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/taskq.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/cyclic.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/pattr.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/strsun.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/random.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/sysmacros.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/stream.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/mac.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/mac_provider.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include <sys/mac_ether.h>
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include "virtiovar.h"
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#include "virtioreg.h"
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Configuration registers */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CONFIG_MAC 0 /* 8bit x 6byte */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CONFIG_STATUS 6 /* 16bit */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Feature bits */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_CSUM (1 << 0) /* Host handles pkts w/ partial csum */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_GUEST_CSUM (1 << 1) /* Guest handles pkts w/ part csum */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_MAC (1 << 5) /* Host has given MAC address. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_GSO (1 << 6) /* Host handles pkts w/ any GSO type */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_GUEST_TSO4 (1 << 7) /* Guest can handle TSOv4 in. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_GUEST_TSO6 (1 << 8) /* Guest can handle TSOv6 in. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_GUEST_ECN (1 << 9) /* Guest can handle TSO[6] w/ ECN in */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_GUEST_UFO (1 << 10) /* Guest can handle UFO in. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_HOST_TSO4 (1 << 11) /* Host can handle TSOv4 in. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_HOST_TSO6 (1 << 12) /* Host can handle TSOv6 in. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_HOST_ECN (1 << 13) /* Host can handle TSO[6] w/ ECN in */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_HOST_UFO (1 << 14) /* Host can handle UFO in. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_MRG_RXBUF (1 << 15) /* Host can merge receive buffers. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_STATUS (1 << 16) /* Config.status available */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_CTRL_VQ (1 << 17) /* Control channel available */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_CTRL_RX (1 << 18) /* Control channel RX mode support */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_CTRL_VLAN (1 << 19) /* Control channel VLAN filtering */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_F_CTRL_RX_EXTRA (1 << 20) /* Extra RX mode control support */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_FEATURE_BITS \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\020" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\1CSUM" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\2GUEST_CSUM" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\6MAC" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\7GSO" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\10GUEST_TSO4" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\11GUEST_TSO6" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\12GUEST_ECN" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\13GUEST_UFO" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\14HOST_TSO4" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\15HOST_TSO6" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\16HOST_ECN" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\17HOST_UFO" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\20MRG_RXBUF" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\21STATUS" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\22CTRL_VQ" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\23CTRL_RX" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\24CTRL_VLAN" \
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "\25CTRL_RX_EXTRA"
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Status */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_S_LINK_UP 1
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#pragma pack(1)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Packet header structure */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct virtio_net_hdr {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t flags;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t gso_type;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint16_t hdr_len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint16_t gso_size;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint16_t csum_start;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint16_t csum_offset;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#pragma pack()
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* flags */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_HDR_GSO_NONE 0 /* gso_type */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_HDR_GSO_TCPV4 1 /* gso_type */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_HDR_GSO_UDP 3 /* gso_type */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_HDR_GSO_TCPV6 4 /* gso_type */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_HDR_GSO_ECN 0x80 /* gso_type, |'ed */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Control virtqueue */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#pragma pack(1)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct virtio_net_ctrl_cmd {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t class;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t command;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#pragma pack()
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_RX 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_RX_PROMISC 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_RX_ALLMULTI 1
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_MAC 1
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_VLAN 2
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_VLAN_ADD 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIRTIO_NET_CTRL_VLAN_DEL 1
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#pragma pack(1)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct virtio_net_ctrl_status {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t ack;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct virtio_net_ctrl_rx {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t onoff;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct virtio_net_ctrl_mac_tbl {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t nentries;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t macs[][ETHERADDRL];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct virtio_net_ctrl_vlan {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint16_t id;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#pragma pack()
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int vioif_quiesce(dev_info_t *);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int vioif_attach(dev_info_t *, ddi_attach_cmd_t);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int vioif_detach(dev_info_t *, ddi_detach_cmd_t);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldDDI_DEFINE_STREAM_OPS(vioif_ops,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel nulldev, /* identify */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel nulldev, /* probe */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel vioif_attach, /* attach */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel vioif_detach, /* detach */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel nodev, /* reset */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel NULL, /* cb_ops */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel D_MP, /* bus_ops */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel NULL, /* power */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel vioif_quiesce /* quiesce */);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic char vioif_ident[] = "VirtIO ethernet driver";
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Standard Module linkage initialization for a Streams driver */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldextern struct mod_ops mod_driverops;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic struct modldrv modldrv = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &mod_driverops, /* Type of module. This one is a driver */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_ident, /* short description */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &vioif_ops /* driver specific ops */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic struct modlinkage modlinkage = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald MODREV_1,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void *)&modldrv,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald NULL,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald },
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldddi_device_acc_attr_t vioif_attr = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DEVICE_ATTR_V0,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_NEVERSWAP_ACC, /* virtio is always native byte order */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_STORECACHING_OK_ACC,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DEFAULT_ACC
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * A mapping represents a binding for a single buffer that is contiguous in the
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * virtual address space.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct vioif_buf_mapping {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald caddr_t vbm_buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_handle_t vbm_dmah;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_acc_handle_t vbm_acch;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_cookie_t vbm_dmac;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int vbm_ncookies;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Rx buffers can be loaned upstream, so the code has
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * to allocate them dynamically.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct vioif_rx_buf {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *rb_sc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald frtn_t rb_frtn;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_buf_mapping rb_mapping;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Tx buffers have two mapping types. One, "inline", is pre-allocated and is
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * used to hold the virtio_net_header. Small packets also get copied there, as
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * it's faster then mapping them. Bigger packets get mapped using the "external"
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * mapping array. An array is used, because a packet may consist of muptiple
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * fragments, so each fragment gets bound to an entry. According to my
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * observations, the number of fragments does not exceed 2, but just in case,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * a bigger, up to VIOIF_INDIRECT_MAX - 1 array is allocated. To save resources,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * the dma handles are allocated lazily in the tx path.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct vioif_tx_buf {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mblk_t *tb_mp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* inline buffer */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_buf_mapping tb_inline_mapping;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* External buffers */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_buf_mapping *tb_external_mapping;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int tb_external_num;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstruct vioif_softc {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_info_t *sc_dev; /* mirrors virtio_softc->sc_dev */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtio_softc sc_virtio;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_handle_t sc_mac_handle;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_register_t *sc_macp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtqueue *sc_rx_vq;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtqueue *sc_tx_vq;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtqueue *sc_ctrl_vq;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int sc_tx_stopped:1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Feature bits. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int sc_rx_csum:1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int sc_tx_csum:1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int sc_tx_tso4:1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int sc_mtu;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint8_t sc_mac[ETHERADDRL];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * For rx buffers, we keep a pointer array, because the buffers
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * can be loaned upstream, and we have to repopulate the array with
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * new members.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_rx_buf **sc_rxbufs;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * For tx, we just allocate an array of buffers. The packet can
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * either be copied into the inline buffer, or the external mapping
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * could be used to map the packet
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *sc_txbufs;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kstat_t *sc_intrstat;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * We "loan" rx buffers upstream and reuse them after they are
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * freed. This lets us avoid allocations in the hot path.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_cache_t *sc_rxbuf_cache;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ulong_t sc_rxloan;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Copying small packets turns out to be faster then mapping them. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned long sc_rxcopy_thresh;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned long sc_txcopy_thresh;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Some statistic coming here */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_ipackets;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_opackets;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_rbytes;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_obytes;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_brdcstxmt;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_brdcstrcv;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_multixmt;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_multircv;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_norecvbuf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_notxbuf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_ierrors;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint64_t sc_oerrors;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define ETHER_HEADER_LEN sizeof (struct ether_header)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* MTU + the ethernet header. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define MAX_PAYLOAD 65535
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define MAX_MTU (MAX_PAYLOAD - ETHER_HEADER_LEN)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define DEFAULT_MTU ETHERMTU
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Yeah, we spend 8M per device. Turns out, there is no point
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * being smart and using merged rx buffers (VIRTIO_NET_F_MRG_RXBUF),
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * because vhost does not support them, and we expect to be used with
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * vhost in production environment.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* The buffer keeps both the packet data and the virtio_net_header. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_RX_SIZE (MAX_PAYLOAD + sizeof (struct virtio_net_hdr))
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * We win a bit on header alignment, but the host wins a lot
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * more on moving aligned buffers. Might need more thought.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_IP_ALIGN 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Maximum number of indirect descriptors, somewhat arbitrary. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_INDIRECT_MAX 128
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * We pre-allocate a reasonably large buffer to copy small packets
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * there. Bigger packets are mapped, packets with multiple
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * cookies are mapped as indirect buffers.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_TX_INLINE_SIZE 2048
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Native queue size for all queues */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_RX_QLEN 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_TX_QLEN 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_CTRL_QLEN 0
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic uchar_t vioif_broadcast[ETHERADDRL] = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_TX_THRESH_MAX 640
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define VIOIF_RX_THRESH_MAX 640
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald#define CACHE_NAME_SIZE 32
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic char vioif_txcopy_thresh[] =
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "vioif_txcopy_thresh";
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic char vioif_rxcopy_thresh[] =
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "vioif_rxcopy_thresh";
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic char *vioif_priv_props[] = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_txcopy_thresh,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_rxcopy_thresh,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald NULL
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Add up to ddi? */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic ddi_dma_cookie_t *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_dma_curr_cookie(ddi_dma_handle_t dmah)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_impl_t *dmah_impl = (void *) dmah;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(dmah_impl->dmai_cookie);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (dmah_impl->dmai_cookie);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_dma_reset_cookie(ddi_dma_handle_t dmah, ddi_dma_cookie_t *dmac)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_impl_t *dmah_impl = (void *) dmah;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dmah_impl->dmai_cookie = dmac;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic link_state_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_link_state(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_virtio.sc_features & VIRTIO_NET_F_STATUS) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (virtio_read_device_config_2(&sc->sc_virtio,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_CONFIG_STATUS) & VIRTIO_NET_S_LINK_UP) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (LINK_STATE_UP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (LINK_STATE_DOWN);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (LINK_STATE_UP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic ddi_dma_attr_t vioif_inline_buf_dma_attr = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DMA_ATTR_V0, /* Version number */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0, /* low address */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFFFFFFFFFF, /* high address */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFF, /* counter register max */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* page alignment */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* burst sizes: 1 - 32 */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* minimum transfer size */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFF, /* max transfer size */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFFFFFFFFF, /* address register max */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* scatter-gather capacity */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* device operates on bytes */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0, /* attr flag: set to 0 */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic ddi_dma_attr_t vioif_mapped_buf_dma_attr = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DMA_ATTR_V0, /* Version number */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0, /* low address */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFFFFFFFFFF, /* high address */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFF, /* counter register max */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* page alignment */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* burst sizes: 1 - 32 */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* minimum transfer size */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFF, /* max transfer size */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0xFFFFFFFFFFFFFFF, /* address register max */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* One entry is used for the virtio_net_hdr on the tx path */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_INDIRECT_MAX - 1, /* scatter-gather capacity */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 1, /* device operates on bytes */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0, /* attr flag: set to 0 */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic ddi_device_acc_attr_t vioif_bufattr = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DEVICE_ATTR_V0,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_NEVERSWAP_ACC,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_STORECACHING_OK_ACC,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DEFAULT_ACC
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_rx_free(caddr_t free_arg)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_rx_buf *buf = (void *) free_arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = buf->rb_sc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_cache_free(sc->sc_rxbuf_cache, buf);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald atomic_dec_ulong(&sc->sc_rxloan);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_rx_construct(void *buffer, void *user_arg, int kmflags)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald _NOTE(ARGUNUSED(kmflags));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = user_arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_rx_buf *buf = buffer;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald size_t len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ddi_dma_alloc_handle(sc->sc_dev, &vioif_mapped_buf_dma_attr,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmah)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Can't allocate dma handle for rx buffer");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_handle;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ddi_dma_mem_alloc(buf->rb_mapping.vbm_dmah,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_RX_SIZE + sizeof (struct virtio_net_hdr),
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &vioif_bufattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald NULL, &buf->rb_mapping.vbm_buf, &len, &buf->rb_mapping.vbm_acch)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Can't allocate rx buffer");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_alloc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(len >= VIOIF_RX_SIZE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ddi_dma_addr_bind_handle(buf->rb_mapping.vbm_dmah, NULL,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->rb_mapping.vbm_buf, len, DDI_DMA_READ | DDI_DMA_STREAMING,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmac,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &buf->rb_mapping.vbm_ncookies)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN, "Can't bind tx buffer");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_bind;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf->rb_mapping.vbm_ncookies <= VIOIF_INDIRECT_MAX);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->rb_sc = sc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->rb_frtn.free_arg = (void *) buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->rb_frtn.free_func = vioif_rx_free;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (0);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_bind:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_mem_free(&buf->rb_mapping.vbm_acch);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_alloc:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_handle:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ENOMEM);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_rx_destruct(void *buffer, void *user_arg)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald _NOTE(ARGUNUSED(user_arg));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_rx_buf *buf = buffer;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf->rb_mapping.vbm_acch);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf->rb_mapping.vbm_acch);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) ddi_dma_unbind_handle(buf->rb_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_mem_free(&buf->rb_mapping.vbm_acch);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_free_mems(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int i;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (i = 0; i < sc->sc_tx_vq->vq_num; i++) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int j;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Tear down the internal mapping. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf->tb_inline_mapping.vbm_acch);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf->tb_inline_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) ddi_dma_unbind_handle(buf->tb_inline_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_mem_free(&buf->tb_inline_mapping.vbm_acch);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_free_handle(&buf->tb_inline_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* We should not see any in-flight buffers at this point. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(!buf->tb_mp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Free all the dma hdnales we allocated lazily. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (j = 0; buf->tb_external_mapping[j].vbm_dmah; j++)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_free_handle(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &buf->tb_external_mapping[j].vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Free the external mapping array. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(buf->tb_external_mapping,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_tx_vq->vq_num);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (i = 0; i < sc->sc_rx_vq->vq_num; i++) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_rx_buf *buf = sc->sc_rxbufs[i];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (buf)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_cache_free(sc->sc_rxbuf_cache, buf);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf *) *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rx_vq->vq_num);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_alloc_mems(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int i, txqsize, rxqsize;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald size_t len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int nsegments;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald txqsize = sc->sc_tx_vq->vq_num;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald rxqsize = sc->sc_rx_vq->vq_num;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_txbufs = kmem_zalloc(sizeof (struct vioif_tx_buf) * txqsize,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald KM_SLEEP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_txbufs == NULL) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Failed to allocate the tx buffers array");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_txalloc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * We don't allocate the rx vioif_bufs, just the pointers, as
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * rx vioif_bufs can be loaned upstream, and we don't know the
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * total number we need.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rxbufs = kmem_zalloc(sizeof (struct vioif_rx_buf *) * rxqsize,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald KM_SLEEP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_rxbufs == NULL) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Failed to allocate the rx buffers pointer array");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_rxalloc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (i = 0; i < txqsize; i++) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Allocate and bind an inline mapping. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ddi_dma_alloc_handle(sc->sc_dev,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &vioif_inline_buf_dma_attr,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_dmah)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Can't allocate dma handle for tx buffer %d", i);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_tx;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ddi_dma_mem_alloc(buf->tb_inline_mapping.vbm_dmah,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_TX_INLINE_SIZE, &vioif_bufattr, DDI_DMA_STREAMING,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_buf,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &len, &buf->tb_inline_mapping.vbm_acch)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Can't allocate tx buffer %d", i);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_tx;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(len >= VIOIF_TX_INLINE_SIZE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ddi_dma_addr_bind_handle(buf->tb_inline_mapping.vbm_dmah,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald NULL, buf->tb_inline_mapping.vbm_buf, len,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &buf->tb_inline_mapping.vbm_dmac, &nsegments)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Can't bind tx buffer %d", i);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_tx;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* We asked for a single segment */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(nsegments == 1);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * We allow up to VIOIF_INDIRECT_MAX - 1 external mappings.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * In reality, I don't expect more then 2-3 used, but who
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * knows.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_external_mapping = kmem_zalloc(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald KM_SLEEP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * The external mapping's dma handles are allocate lazily,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * as we don't expect most of them to be used..
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (0);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_tx:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (i = 0; i < txqsize; i++) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (buf->tb_inline_mapping.vbm_dmah)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) ddi_dma_unbind_handle(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_inline_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (buf->tb_inline_mapping.vbm_acch)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_mem_free(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &buf->tb_inline_mapping.vbm_acch);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (buf->tb_inline_mapping.vbm_dmah)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_free_handle(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &buf->tb_inline_mapping.vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (buf->tb_external_mapping)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(buf->tb_external_mapping,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct vioif_tx_buf) *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_INDIRECT_MAX - 1);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf) * rxqsize);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_rxalloc:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) * txqsize);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_txalloc:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ENOMEM);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* ARGSUSED */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldint
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* ARGSUSED */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldint
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_promisc(void *arg, boolean_t on)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* ARGSUSED */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldint
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_unicst(void *arg, const uint8_t *macaddr)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmelstatic uint_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_add_rx(struct vioif_softc *sc, int kmflag)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel uint_t num_added = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel for (;;) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel struct vq_entry *ve;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel struct vioif_rx_buf *buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel ve = vq_alloc_entry(sc->sc_rx_vq);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (!ve) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * Out of free descriptors - ring already full.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * It would be better to update sc_norxdescavail
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * but MAC does not ask for this info, hence we
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * update sc_norecvbuf.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel sc->sc_norecvbuf++;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel break;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel buf = sc->sc_rxbufs[ve->qe_index];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (!buf) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /* First run, allocate the buffer. */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel buf = kmem_cache_alloc(sc->sc_rxbuf_cache, kmflag);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel sc->sc_rxbufs[ve->qe_index] = buf;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /* Still nothing? Bye. */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (!buf) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel dev_err(sc->sc_dev, CE_WARN,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel "Can't allocate rx buffer");
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel sc->sc_norecvbuf++;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel vq_free_entry(sc->sc_rx_vq, ve);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel break;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel ASSERT(buf->rb_mapping.vbm_ncookies >= 1);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * For an unknown reason, the virtio_net_hdr must be placed
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * as a separate virtio queue entry.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel virtio_ve_add_indirect_buf(ve,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel buf->rb_mapping.vbm_dmac.dmac_laddress,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel sizeof (struct virtio_net_hdr), B_FALSE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /* Add the rest of the first cookie. */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel virtio_ve_add_indirect_buf(ve,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel buf->rb_mapping.vbm_dmac.dmac_laddress +
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel sizeof (struct virtio_net_hdr),
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel buf->rb_mapping.vbm_dmac.dmac_size -
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel sizeof (struct virtio_net_hdr), B_FALSE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * If the buffer consists of a single cookie (unlikely for a
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * 64-k buffer), we are done. Otherwise, add the rest of the
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * cookies using indirect entries.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (buf->rb_mapping.vbm_ncookies > 1) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel ddi_dma_cookie_t *first_extra_dmac;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel ddi_dma_cookie_t dmac;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel first_extra_dmac =
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel vioif_dma_curr_cookie(buf->rb_mapping.vbm_dmah);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel ddi_dma_nextcookie(buf->rb_mapping.vbm_dmah, &dmac);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel virtio_ve_add_cookie(ve, buf->rb_mapping.vbm_dmah,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel dmac, buf->rb_mapping.vbm_ncookies - 1, B_FALSE);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel vioif_dma_reset_cookie(buf->rb_mapping.vbm_dmah,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel first_extra_dmac);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel virtio_push_chain(ve, B_FALSE);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel num_added++;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel return (num_added);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmelstatic uint_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_populate_rx(struct vioif_softc *sc, int kmflag)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel uint_t num_added = vioif_add_rx(sc, kmflag);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (num_added > 0)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_sync_vq(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel return (num_added);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmelstatic uint_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_process_rx(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vq_entry *ve;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_rx_buf *buf;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel mblk_t *mphead = NULL, *lastmp = NULL, *mp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t len;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel uint_t num_processed = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald while ((ve = virtio_pull_chain(sc->sc_rx_vq, &len))) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf = sc->sc_rxbufs[ve->qe_index];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (len < sizeof (struct virtio_net_hdr)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN, "RX: Cnain too small: %u",
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald len - (uint32_t)sizeof (struct virtio_net_hdr));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_ierrors++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_chain(ve);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald continue;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald len -= sizeof (struct virtio_net_hdr);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * We copy small packets that happen to fit into a single
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * cookie and reuse the buffers. For bigger ones, we loan
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * the buffers upstream.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (len < sc->sc_rxcopy_thresh) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp = allocb(len, 0);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!mp) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_norecvbuf++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_ierrors++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_chain(ve);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald bcopy((char *)buf->rb_mapping.vbm_buf +
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct virtio_net_hdr), mp->b_rptr, len);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp->b_wptr = mp->b_rptr + len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp = desballoc((unsigned char *)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->rb_mapping.vbm_buf +
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct virtio_net_hdr) +
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!mp) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_norecvbuf++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_ierrors++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_chain(ve);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp->b_wptr = mp->b_rptr + len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald atomic_inc_ulong(&sc->sc_rxloan);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Buffer loaned, we will have to allocate a new one
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * for this slot.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rxbufs[ve->qe_index] = NULL;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * virtio-net does not tell us if this packet is multicast
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * or broadcast, so we have to check it.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (mp->b_rptr[0] & 0x1) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_multircv++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald else
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_brdcstrcv++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rbytes += len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_ipackets++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_chain(ve);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (lastmp == NULL) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel mphead = mp;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel } else {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel lastmp->b_next = mp;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel lastmp = mp;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel num_processed++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (mphead != NULL) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel mac_rx(sc->sc_mac_handle, NULL, mphead);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel return (num_processed);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmelstatic uint_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_reclaim_used_tx(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vq_entry *ve;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mblk_t *mp;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel uint_t num_reclaimed = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald while ((ve = virtio_pull_chain(sc->sc_tx_vq, &len))) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* We don't chain descriptors for tx, so don't expect any. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(!ve->qe_next);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf = &sc->sc_txbufs[ve->qe_index];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp = buf->tb_mp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_mp = NULL;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (mp) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel for (int i = 0; i < buf->tb_external_num; i++)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) ddi_dma_unbind_handle(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_external_mapping[i].vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_chain(ve);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* External mapping used, mp was not freed in vioif_send() */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (mp)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald freemsg(mp);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel num_reclaimed++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel if (sc->sc_tx_stopped && num_reclaimed > 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_tx_stopped = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_tx_update(sc->sc_mac_handle);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel return (num_reclaimed);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* sc will be used to update stat counters. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* ARGSUSED */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic inline void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_tx_inline(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald size_t msg_size)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf = &sc->sc_txbufs[ve->qe_index];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Frees mp */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mcopymsg(mp, buf->tb_inline_mapping.vbm_buf +
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct virtio_net_hdr));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_ve_add_indirect_buf(ve,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_inline_mapping.vbm_dmac.dmac_laddress +
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct virtio_net_hdr), msg_size, B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic inline int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_tx_lazy_handle_alloc(struct vioif_softc *sc, struct vioif_tx_buf *buf,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int i)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int ret = DDI_SUCCESS;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!buf->tb_external_mapping[i].vbm_dmah) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = ddi_dma_alloc_handle(sc->sc_dev,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &vioif_mapped_buf_dma_attr, DDI_DMA_SLEEP, NULL,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &buf->tb_external_mapping[i].vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret != DDI_SUCCESS) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Can't allocate dma handle for external tx buffer");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ret);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic inline int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_tx_external(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald size_t msg_size)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald _NOTE(ARGUNUSED(msg_size));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mblk_t *nmp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int i, j;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int ret = DDI_SUCCESS;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf = &sc->sc_txbufs[ve->qe_index];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(buf);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_external_num = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald i = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald nmp = mp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald while (nmp) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald size_t len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_dma_cookie_t dmac;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald unsigned int ncookies;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald len = MBLKL(nmp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * For some reason, the network stack can
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * actually send us zero-length fragments.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (len == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald nmp = nmp->b_cont;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald continue;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = vioif_tx_lazy_handle_alloc(sc, buf, i);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret != DDI_SUCCESS) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_notxbuf++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_oerrors++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_lazy_alloc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = ddi_dma_addr_bind_handle(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_external_mapping[i].vbm_dmah, NULL,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (caddr_t)nmp->b_rptr, len,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DMA_WRITE | DDI_DMA_STREAMING,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald DDI_DMA_SLEEP, NULL, &dmac, &ncookies);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret != DDI_SUCCESS) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_oerrors++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_NOTE,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "TX: Failed to bind external handle");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_bind;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Check if we still fit into the indirect table. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (virtio_ve_indirect_available(ve) < ncookies) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_NOTE,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "TX: Indirect descriptor table limit reached."
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald " It took %d fragments.", i);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_notxbuf++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_oerrors++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = DDI_FAILURE;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_limit;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_ve_add_cookie(ve, buf->tb_external_mapping[i].vbm_dmah,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dmac, ncookies, B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald nmp = nmp->b_cont;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald i++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_external_num = i;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Save the mp to free it when the packet is sent. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_mp = mp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_limit:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_bind:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_lazy_alloc:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (j = 0; j < i; j++) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) ddi_dma_unbind_handle(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_external_mapping[j].vbm_dmah);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ret);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic boolean_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_send(struct vioif_softc *sc, mblk_t *mp)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vq_entry *ve;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_tx_buf *buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtio_net_hdr *net_header = NULL;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald size_t msg_size = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t csum_start;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t csum_stuff;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t csum_flags;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t lso_flags;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t lso_mss;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mblk_t *nmp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int ret;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald boolean_t lso_required = B_FALSE;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (nmp = mp; nmp; nmp = nmp->b_cont)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald msg_size += MBLKL(nmp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_tx_tso4) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_lso_get(mp, &lso_mss, &lso_flags);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald lso_required = (lso_flags & HW_LSO);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ve = vq_alloc_entry(sc->sc_tx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!ve) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_notxbuf++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Out of free descriptors - try later. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_FALSE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf = &sc->sc_txbufs[ve->qe_index];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Use the inline buffer of the first entry for the virtio_net_hdr. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) memset(buf->tb_inline_mapping.vbm_buf, 0,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct virtio_net_hdr));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald net_header = (struct virtio_net_hdr *)buf->tb_inline_mapping.vbm_buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_hcksum_get(mp, &csum_start, &csum_stuff, NULL,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald NULL, &csum_flags);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* They want us to do the TCP/UDP csum calculation. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (csum_flags & HCK_PARTIALCKSUM) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct ether_header *eth_header;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int eth_hsize;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Did we ask for it? */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(sc->sc_tx_csum);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* We only asked for partial csum packets. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(!(csum_flags & HCK_IPV4_HDRCKSUM));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ASSERT(!(csum_flags & HCK_FULLCKSUM));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald eth_header = (void *) mp->b_rptr;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (eth_header->ether_type == htons(ETHERTYPE_VLAN)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald eth_hsize = sizeof (struct ether_vlan_header);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald eth_hsize = sizeof (struct ether_header);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald net_header->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald net_header->csum_start = eth_hsize + csum_start;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald net_header->csum_offset = csum_stuff - csum_start;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* setup LSO fields if required */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (lso_required) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald net_header->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald net_header->gso_size = (uint16_t)lso_mss;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_ve_add_indirect_buf(ve,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald buf->tb_inline_mapping.vbm_dmac.dmac_laddress,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct virtio_net_hdr), B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* meanwhile update the statistic */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (mp->b_rptr[0] & 0x1) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_multixmt++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald else
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_brdcstxmt++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * We copy small packets into the inline buffer. The bigger ones
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * get mapped using the mapped buffer.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (msg_size < sc->sc_txcopy_thresh) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_tx_inline(sc, ve, mp, msg_size);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* statistic gets updated by vioif_tx_external when fail */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = vioif_tx_external(sc, ve, mp, msg_size);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret != DDI_SUCCESS)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_tx_external;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_push_chain(ve, B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_opackets++;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_obytes += msg_size;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_tx_external:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vq_free_entry(sc->sc_tx_vq, ve);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * vioif_tx_external can fail when the buffer does not fit into the
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * indirect descriptor table. Free the mp. I don't expect this ever
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * to happen.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald freemsg(mp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldmblk_t *
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_tx(void *arg, mblk_t *mp)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mblk_t *nmp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald while (mp != NULL) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald nmp = mp->b_next;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp->b_next = NULL;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!vioif_send(sc, mp)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_tx_stopped = 1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp->b_next = nmp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mp = nmp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (mp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldint
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_start(void *arg)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel struct vq_entry *ve;
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel uint32_t len;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_link_update(sc->sc_mac_handle,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_link_state(sc));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_start_vq_intr(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * Don't start interrupts on sc_tx_vq. We use VIRTIO_F_NOTIFY_ON_EMPTY,
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * so the device will send a transmit interrupt when the queue is empty
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * and we can reclaim it in one sweep.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * Clear any data that arrived early on the receive queue and populate
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * it with free buffers that the device can use moving forward.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel while ((ve = virtio_pull_chain(sc->sc_rx_vq, &len)) != NULL) {
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel virtio_free_chain(ve);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel }
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel (void) vioif_populate_rx(sc, KM_SLEEP);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvoid
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_stop(void *arg)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* ARGSUSED */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_stat(void *arg, uint_t stat, uint64_t *val)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald switch (stat) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_IERRORS:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_ierrors;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_OERRORS:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_oerrors;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_MULTIRCV:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_multircv;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_BRDCSTRCV:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_brdcstrcv;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_MULTIXMT:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_multixmt;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_BRDCSTXMT:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_brdcstxmt;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_IPACKETS:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_ipackets;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_RBYTES:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_rbytes;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_OPACKETS:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_opackets;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_OBYTES:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_obytes;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_NORCVBUF:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_norecvbuf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_NOXMTBUF:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = sc->sc_notxbuf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_STAT_IFSPEED:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* always 1 Gbit */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = 1000000000ULL;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case ETHER_STAT_LINK_DUPLEX:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* virtual device, always full-duplex */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *val = LINK_DUPLEX_FULL;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald default:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ENOTSUP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_set_prop_private(struct vioif_softc *sc, const char *pr_name,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint_t pr_valsize, const void *pr_val)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald _NOTE(ARGUNUSED(pr_valsize));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald long result;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (pr_val == NULL)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (EINVAL);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (result < 0 || result > VIOIF_TX_THRESH_MAX)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (EINVAL);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_txcopy_thresh = result;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (pr_val == NULL)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (EINVAL);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (result < 0 || result > VIOIF_RX_THRESH_MAX)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (EINVAL);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rxcopy_thresh = result;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (0);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint_t pr_valsize, const void *pr_val)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald const uint32_t *new_mtu;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int err;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald switch (pr_num) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_PROP_MTU:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald new_mtu = pr_val;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (*new_mtu > MAX_MTU) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (EINVAL);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald err = mac_maxsdu_update(sc->sc_mac_handle, *new_mtu);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (err) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (err);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_PROP_PRIVATE:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald err = vioif_set_prop_private(sc, pr_name,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald pr_valsize, pr_val);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (err)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (err);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald default:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ENOTSUP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (0);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_get_prop_private(struct vioif_softc *sc, const char *pr_name,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint_t pr_valsize, void *pr_val)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int err = ENOTSUP;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int value;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald value = sc->sc_txcopy_thresh;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald err = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto done;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald value = sc->sc_rxcopy_thresh;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald err = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto done;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonalddone:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (err == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) snprintf(pr_val, pr_valsize, "%d", value);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (err);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint_t pr_valsize, void *pr_val)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int err = ENOTSUP;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald switch (pr_num) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_PROP_PRIVATE:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald err = vioif_get_prop_private(sc, pr_name,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald pr_valsize, pr_val);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald default:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (err);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_prop_info_handle_t prh)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald char valstr[64];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int value;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald switch (pr_num) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_PROP_MTU:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_prop_info_set_range_uint32(prh, ETHERMIN, MAX_MTU);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_PROP_PRIVATE:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald bzero(valstr, sizeof (valstr));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald value = sc->sc_txcopy_thresh;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else if (strcmp(pr_name,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_rxcopy_thresh) == 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald value = sc->sc_rxcopy_thresh;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) snprintf(valstr, sizeof (valstr), "%d", value);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald default:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic boolean_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_getcapab(void *arg, mac_capab_t cap, void *cap_data)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = arg;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald switch (cap) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_CAPAB_HCKSUM:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_tx_csum) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t *txflags = cap_data;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *txflags = HCKSUM_INET_PARTIAL;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_FALSE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case MAC_CAPAB_LSO:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_tx_tso4) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_capab_lso_t *cap_lso = cap_data;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald cap_lso->lso_basic_tcp_ipv4.lso_max = MAX_MTU;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_TRUE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_FALSE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald default:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (B_FALSE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic mac_callbacks_t vioif_m_callbacks = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_callbacks = (MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO),
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_getstat = vioif_stat,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_start = vioif_start,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_stop = vioif_stop,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_setpromisc = vioif_promisc,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_multicst = vioif_multicst,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_unicst = vioif_unicst,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_tx = vioif_tx,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Optional callbacks */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_reserved = NULL, /* reserved */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_ioctl = NULL, /* mc_ioctl */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_getcapab = vioif_getcapab, /* mc_getcapab */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_open = NULL, /* mc_open */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_close = NULL, /* mc_close */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_setprop = vioif_setprop,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_getprop = vioif_getprop,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald .mc_propinfo = vioif_propinfo,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald};
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_show_features(struct vioif_softc *sc, const char *prefix,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t features)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald char buf[512];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald char *bufp = buf;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald char *bufend = buf + sizeof (buf);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* LINTED E_PTRDIFF_OVERFLOW */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald bufp += snprintf(bufp, bufend - bufp, prefix);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* LINTED E_PTRDIFF_OVERFLOW */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald bufp += virtio_show_features(features, bufp, bufend - bufp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald *bufp = '\0';
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Using '!' to only CE_NOTE this to the system log. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_NOTE, "!%s Vioif (%b)", buf, features,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_FEATURE_BITS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Find out which features are supported by the device and
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * choose which ones we wish to use.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_dev_features(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald uint32_t host_features;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald host_features = virtio_negotiate_features(&sc->sc_virtio,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_F_CSUM |
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_F_HOST_TSO4 |
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_F_HOST_ECN |
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_F_MAC |
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_F_STATUS |
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_F_RING_INDIRECT_DESC |
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_F_NOTIFY_ON_EMPTY);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_show_features(sc, "Host features: ", host_features);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_show_features(sc, "Negotiated features: ",
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_virtio.sc_features);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!(sc->sc_virtio.sc_features & VIRTIO_F_RING_INDIRECT_DESC)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_NOTE,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Host does not support RING_INDIRECT_DESC, bye.");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_has_feature(struct vioif_softc *sc, uint32_t feature)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (virtio_has_feature(&sc->sc_virtio, feature));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_set_mac(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int i;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (i = 0; i < ETHERADDRL; i++) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_write_device_config_1(&sc->sc_virtio,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_CONFIG_MAC + i, sc->sc_mac[i]);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* Get the mac address out of the hardware, or make up one. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_get_mac(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int i;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_virtio.sc_features & VIRTIO_NET_F_MAC) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald for (i = 0; i < ETHERADDRL; i++) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_mac[i] = virtio_read_device_config_1(
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald &sc->sc_virtio,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_NET_CONFIG_MAC + i);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_NOTE, "Got MAC address from host: %s",
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ether_sprintf((struct ether_addr *)sc->sc_mac));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Get a few random bytes */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) random_get_pseudo_bytes(sc->sc_mac, ETHERADDRL);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Make sure it's a unicast MAC */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_mac[0] &= ~1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Set the "locally administered" bit */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_mac[1] |= 2;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_set_mac(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_NOTE,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Generated a random MAC address: %s",
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ether_sprintf((struct ether_addr *)sc->sc_mac));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Virtqueue interrupt handlers
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* ARGSUSED */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonalduint_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_rx_handler(caddr_t arg1, caddr_t arg2)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtio_softc *vsc = (void *) arg1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = container_of(vsc,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc, sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * The return values of these functions are not needed but they make
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * debugging interrupts simpler because you can use them to detect when
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * stuff was processed and repopulated in this handler.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) vioif_process_rx(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) vioif_populate_rx(sc, KM_NOSLEEP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_INTR_CLAIMED);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald/* ARGSUSED */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonalduint_t
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_tx_handler(caddr_t arg1, caddr_t arg2)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtio_softc *vsc = (void *)arg1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc = container_of(vsc,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc, sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel /*
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * The return value of this function is not needed but makes debugging
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * interrupts simpler because you can use it to detect if anything was
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel * reclaimed in this handler.
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel */
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel (void) vioif_reclaim_used_tx(sc);
970db7b7a5b4656c659fc7c5226da7be313dc336Dan Kimmel
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_INTR_CLAIMED);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_register_ints(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int ret;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtio_int_handler vioif_vq_h[] = {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald { vioif_rx_handler },
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald { vioif_tx_handler },
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald { NULL }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald };
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = virtio_register_ints(&sc->sc_virtio, NULL, vioif_vq_h);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ret);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic void
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_check_features(struct vioif_softc *sc)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (vioif_has_feature(sc, VIRTIO_NET_F_CSUM)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* The GSO/GRO featured depend on CSUM, check them here. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_tx_csum = 1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rx_csum = 1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!vioif_has_feature(sc, VIRTIO_NET_F_GUEST_CSUM)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rx_csum = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald cmn_err(CE_NOTE, "Csum enabled.");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (vioif_has_feature(sc, VIRTIO_NET_F_HOST_TSO4)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_tx_tso4 = 1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * We don't seem to have a way to ask the system
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * not to send us LSO packets with Explicit
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Congestion Notification bit set, so we require
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * the device to support it in order to do
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * LSO.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!vioif_has_feature(sc, VIRTIO_NET_F_HOST_ECN)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_NOTE,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "TSO4 supported, but not ECN. "
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Not using LSO.");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_tx_tso4 = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald } else {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald cmn_err(CE_NOTE, "LSO enabled");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int ret, instance;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct virtio_softc *vsc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_register_t *macp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald char cache_name[CACHE_NAME_SIZE];
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald instance = ddi_get_instance(devinfo);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald switch (cmd) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case DDI_ATTACH:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case DDI_RESUME:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case DDI_PM_RESUME:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* We do not support suspend/resume for vioif. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald default:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_set_driver_private(devinfo, sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vsc = &sc->sc_virtio;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Duplicate for less typing */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_dev = devinfo;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vsc->sc_dev = devinfo;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Initialize interrupt kstat.
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller",
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald KSTAT_TYPE_INTR, 1, 0);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_intrstat == NULL) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(devinfo, CE_WARN, "kstat_create failed");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_intrstat;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kstat_install(sc->sc_intrstat);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* map BAR 0 */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = ddi_regs_map_setup(devinfo, 1,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (caddr_t *)&sc->sc_virtio.sc_io_addr,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald 0, 0, &vioif_attr, &sc->sc_virtio.sc_ioh);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret != DDI_SUCCESS) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(devinfo, CE_WARN, "unable to map bar 0: %d", ret);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_map;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_device_reset(&sc->sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = vioif_dev_features(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_features;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vsc->sc_nvqs = vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) snprintf(cache_name, CACHE_NAME_SIZE, "vioif%d_rx", instance);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rxbuf_cache = kmem_cache_create(cache_name,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sizeof (struct vioif_rx_buf), 0, vioif_rx_construct,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_rx_destruct, NULL, sc, NULL, KM_SLEEP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_rxbuf_cache == NULL) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN, "Can't allocate the buffer cache");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_cache;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = vioif_register_ints(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(sc->sc_dev, CE_WARN,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "Failed to allocate interrupt(s)!");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_ints;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /*
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * Register layout determined, can now access the
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald * device-specific bits
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_get_mac(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rx_vq = virtio_alloc_vq(&sc->sc_virtio, 0,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_RX_QLEN, VIOIF_INDIRECT_MAX, "rx");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!sc->sc_rx_vq)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_alloc1;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_tx_vq = virtio_alloc_vq(&sc->sc_virtio, 1,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_TX_QLEN, VIOIF_INDIRECT_MAX, "tx");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!sc->sc_rx_vq)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_alloc2;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_tx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_ctrl_vq = virtio_alloc_vq(&sc->sc_virtio, 2,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIOIF_CTRL_QLEN, 0, "ctrl");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (!sc->sc_ctrl_vq) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_alloc3;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_ctrl_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_set_status(&sc->sc_virtio,
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rxloan = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* set some reasonable-small default values */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_rxcopy_thresh = 300;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_txcopy_thresh = 300;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_mtu = ETHERMTU;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_check_features(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (vioif_alloc_mems(sc))
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_alloc_mems;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(devinfo, CE_WARN, "Failed to allocate a mac_register");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_macalloc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_driver = sc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_dip = devinfo;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_src_addr = sc->sc_mac;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_callbacks = &vioif_m_callbacks;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_min_sdu = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_max_sdu = sc->sc_mtu;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_margin = VLAN_TAGSZ;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald macp->m_priv_props = vioif_priv_props;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald sc->sc_macp = macp;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* Pre-fill the rx ring. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) vioif_populate_rx(sc, KM_SLEEP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = mac_register(macp, &sc->sc_mac_handle);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret != 0) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(devinfo, CE_WARN, "vioif_attach: "
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald "mac_register() failed, ret=%d", ret);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_register;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = virtio_enable_ints(&sc->sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(devinfo, CE_WARN, "Failed to enable interrupts");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald goto exit_enable_ints;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_link_update(sc->sc_mac_handle, LINK_STATE_UP);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_enable_ints:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald (void) mac_unregister(sc->sc_mac_handle);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_register:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_free(macp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_macalloc:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_free_mems(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_alloc_mems:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_release_ints(&sc->sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_ctrl_vq)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_vq(sc->sc_ctrl_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_alloc3:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_vq(sc->sc_tx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_alloc2:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_vq(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_alloc1:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_ints:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_cache_destroy(sc->sc_rxbuf_cache);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_cache:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_features:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_regs_map_free(&sc->sc_virtio.sc_ioh);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_intrstat:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit_map:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kstat_delete(sc->sc_intrstat);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(sc, sizeof (struct vioif_softc));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldexit:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if ((sc = ddi_get_driver_private(devinfo)) == NULL)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald switch (cmd) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case DDI_DETACH:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald break;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald case DDI_PM_SUSPEND:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald /* We do not support suspend/resume for vioif. */
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald default:
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (sc->sc_rxloan) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald dev_err(devinfo, CE_WARN, "!Some rx buffers are still upstream,"
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald " not detaching.");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_tx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_release_ints(&sc->sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (mac_unregister(sc->sc_mac_handle)) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_free(sc->sc_macp);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald vioif_free_mems(sc);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_vq(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_free_vq(sc->sc_tx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_device_reset(&sc->sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ddi_regs_map_free(&sc->sc_virtio.sc_ioh);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_cache_destroy(sc->sc_rxbuf_cache);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kstat_delete(sc->sc_intrstat);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald kmem_free(sc, sizeof (struct vioif_softc));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldstatic int
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldvioif_quiesce(dev_info_t *devinfo)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald struct vioif_softc *sc;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if ((sc = ddi_get_driver_private(devinfo)) == NULL)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_FAILURE);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_rx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_stop_vq_intr(sc->sc_tx_vq);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald virtio_device_reset(&sc->sc_virtio);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (DDI_SUCCESS);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldint
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald_init(void)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int ret = 0;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_init_ops(&vioif_ops, "vioif");
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = mod_install(&modlinkage);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret != DDI_SUCCESS) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_fini_ops(&vioif_ops);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ret);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (0);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldint
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald_fini(void)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald int ret;
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald ret = mod_remove(&modlinkage);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald if (ret == DDI_SUCCESS) {
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald mac_fini_ops(&vioif_ops);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald }
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (ret);
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald
8a324c92216752a3ac2de7c31f554588932de707Dan McDonaldint
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald_info(struct modinfo *pModinfo)
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald{
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald return (mod_info(&modlinkage, pModinfo));
8a324c92216752a3ac2de7c31f554588932de707Dan McDonald}