hyperv/hn: Cosmetic cleanup; no functional changes.
MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8389
This commit is contained in:
parent
d9fea9f287
commit
ba015837bf
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=308162
@ -59,62 +59,41 @@ __FBSDID("$FreeBSD$");
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/buf_ring.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/buf_ring.h>
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/in_cksum.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/rndis.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
#include <net/if_var.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/rndis.h>
|
||||
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcp_lro.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip6.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/frame.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
|
||||
#include <machine/intr_machdep.h>
|
||||
|
||||
#include <machine/in_cksum.h>
|
||||
|
||||
#include <dev/hyperv/include/hyperv.h>
|
||||
#include <dev/hyperv/include/hyperv_busdma.h>
|
||||
@ -129,24 +108,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "vmbus_if.h"
|
||||
|
||||
/* Short for Hyper-V network interface */
|
||||
#define NETVSC_DEVNAME "hn"
|
||||
|
||||
/*
|
||||
* It looks like offset 0 of buf is reserved to hold the softc pointer.
|
||||
* The sc pointer evidently not needed, and is not presently populated.
|
||||
* The packet offset is where the netvsc_packet starts in the buffer.
|
||||
*/
|
||||
#define HV_NV_SC_PTR_OFFSET_IN_BUF 0
|
||||
#define HV_NV_PACKET_OFFSET_IN_BUF 16
|
||||
#define HN_RING_CNT_DEF_MAX 8
|
||||
|
||||
/* YYY should get it from the underlying channel */
|
||||
#define HN_TX_DESC_CNT 512
|
||||
|
||||
#define HN_LROENT_CNT_DEF 128
|
||||
|
||||
#define HN_RING_CNT_DEF_MAX 8
|
||||
|
||||
#define HN_RNDIS_PKT_LEN \
|
||||
(sizeof(struct rndis_packet_msg) + \
|
||||
HN_RNDIS_PKTINFO_SIZE(HN_NDIS_HASH_VALUE_SIZE) + \
|
||||
@ -166,50 +132,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define HN_EARLY_TXEOF_THRESH 8
|
||||
|
||||
#define HN_RXINFO_VLAN 0x0001
|
||||
#define HN_RXINFO_CSUM 0x0002
|
||||
#define HN_RXINFO_HASHINF 0x0004
|
||||
#define HN_RXINFO_HASHVAL 0x0008
|
||||
#define HN_RXINFO_ALL \
|
||||
(HN_RXINFO_VLAN | \
|
||||
HN_RXINFO_CSUM | \
|
||||
HN_RXINFO_HASHINF | \
|
||||
HN_RXINFO_HASHVAL)
|
||||
|
||||
#define HN_PKTBUF_LEN_DEF (16 * 1024)
|
||||
|
||||
struct hn_txdesc {
|
||||
#ifndef HN_USE_TXDESC_BUFRING
|
||||
SLIST_ENTRY(hn_txdesc) link;
|
||||
#endif
|
||||
struct mbuf *m;
|
||||
struct hn_tx_ring *txr;
|
||||
int refs;
|
||||
uint32_t flags; /* HN_TXD_FLAG_ */
|
||||
struct hn_nvs_sendctx send_ctx;
|
||||
uint32_t chim_index;
|
||||
int chim_size;
|
||||
|
||||
bus_dmamap_t data_dmap;
|
||||
|
||||
bus_addr_t rndis_pkt_paddr;
|
||||
struct rndis_packet_msg *rndis_pkt;
|
||||
bus_dmamap_t rndis_pkt_dmap;
|
||||
};
|
||||
|
||||
#define HN_TXD_FLAG_ONLIST 0x1
|
||||
#define HN_TXD_FLAG_DMAMAP 0x2
|
||||
|
||||
#define HN_NDIS_VLAN_INFO_INVALID 0xffffffff
|
||||
#define HN_NDIS_RXCSUM_INFO_INVALID 0
|
||||
#define HN_NDIS_HASH_INFO_INVALID 0
|
||||
|
||||
struct hn_rxinfo {
|
||||
uint32_t vlan_info;
|
||||
uint32_t csum_info;
|
||||
uint32_t hash_info;
|
||||
uint32_t hash_value;
|
||||
};
|
||||
#define HN_LROENT_CNT_DEF 128
|
||||
|
||||
#define HN_LRO_LENLIM_MULTIRX_DEF (12 * ETHERMTU)
|
||||
#define HN_LRO_LENLIM_DEF (25 * ETHERMTU)
|
||||
@ -220,8 +145,8 @@ struct hn_rxinfo {
|
||||
|
||||
#define HN_LOCK_INIT(sc) \
|
||||
sx_init(&(sc)->hn_lock, device_get_nameunit((sc)->hn_dev))
|
||||
#define HN_LOCK_ASSERT(sc) sx_assert(&(sc)->hn_lock, SA_XLOCKED)
|
||||
#define HN_LOCK_DESTROY(sc) sx_destroy(&(sc)->hn_lock)
|
||||
#define HN_LOCK_ASSERT(sc) sx_assert(&(sc)->hn_lock, SA_XLOCKED)
|
||||
#define HN_LOCK(sc) sx_xlock(&(sc)->hn_lock)
|
||||
#define HN_UNLOCK(sc) sx_xunlock(&(sc)->hn_lock)
|
||||
|
||||
@ -232,199 +157,276 @@ struct hn_rxinfo {
|
||||
#define HN_CSUM_IP6_HWASSIST(sc) \
|
||||
((sc)->hn_tx_ring[0].hn_csum_assist & HN_CSUM_IP6_MASK)
|
||||
|
||||
/*
|
||||
* Globals
|
||||
*/
|
||||
struct hn_txdesc {
|
||||
#ifndef HN_USE_TXDESC_BUFRING
|
||||
SLIST_ENTRY(hn_txdesc) link;
|
||||
#endif
|
||||
struct mbuf *m;
|
||||
struct hn_tx_ring *txr;
|
||||
int refs;
|
||||
uint32_t flags; /* HN_TXD_FLAG_ */
|
||||
struct hn_nvs_sendctx send_ctx;
|
||||
uint32_t chim_index;
|
||||
int chim_size;
|
||||
|
||||
bus_dmamap_t data_dmap;
|
||||
|
||||
bus_addr_t rndis_pkt_paddr;
|
||||
struct rndis_packet_msg *rndis_pkt;
|
||||
bus_dmamap_t rndis_pkt_dmap;
|
||||
};
|
||||
|
||||
#define HN_TXD_FLAG_ONLIST 0x0001
|
||||
#define HN_TXD_FLAG_DMAMAP 0x0002
|
||||
|
||||
struct hn_rxinfo {
|
||||
uint32_t vlan_info;
|
||||
uint32_t csum_info;
|
||||
uint32_t hash_info;
|
||||
uint32_t hash_value;
|
||||
};
|
||||
|
||||
#define HN_RXINFO_VLAN 0x0001
|
||||
#define HN_RXINFO_CSUM 0x0002
|
||||
#define HN_RXINFO_HASHINF 0x0004
|
||||
#define HN_RXINFO_HASHVAL 0x0008
|
||||
#define HN_RXINFO_ALL \
|
||||
(HN_RXINFO_VLAN | \
|
||||
HN_RXINFO_CSUM | \
|
||||
HN_RXINFO_HASHINF | \
|
||||
HN_RXINFO_HASHVAL)
|
||||
|
||||
#define HN_NDIS_VLAN_INFO_INVALID 0xffffffff
|
||||
#define HN_NDIS_RXCSUM_INFO_INVALID 0
|
||||
#define HN_NDIS_HASH_INFO_INVALID 0
|
||||
|
||||
static int hn_probe(device_t);
|
||||
static int hn_attach(device_t);
|
||||
static int hn_detach(device_t);
|
||||
static int hn_shutdown(device_t);
|
||||
static void hn_chan_callback(struct vmbus_channel *,
|
||||
void *);
|
||||
|
||||
static void hn_init(void *);
|
||||
static int hn_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void hn_start(struct ifnet *);
|
||||
static int hn_transmit(struct ifnet *, struct mbuf *);
|
||||
static void hn_xmit_qflush(struct ifnet *);
|
||||
static int hn_ifmedia_upd(struct ifnet *);
|
||||
static void hn_ifmedia_sts(struct ifnet *,
|
||||
struct ifmediareq *);
|
||||
|
||||
static int hn_rndis_rxinfo(const void *, int,
|
||||
struct hn_rxinfo *);
|
||||
static void hn_rndis_rx_data(struct hn_rx_ring *,
|
||||
const void *, int);
|
||||
static void hn_rndis_rx_status(struct hn_softc *,
|
||||
const void *, int);
|
||||
|
||||
static void hn_nvs_handle_notify(struct hn_softc *,
|
||||
const struct vmbus_chanpkt_hdr *);
|
||||
static void hn_nvs_handle_comp(struct hn_softc *,
|
||||
struct vmbus_channel *,
|
||||
const struct vmbus_chanpkt_hdr *);
|
||||
static void hn_nvs_handle_rxbuf(struct hn_rx_ring *,
|
||||
struct vmbus_channel *,
|
||||
const struct vmbus_chanpkt_hdr *);
|
||||
static void hn_nvs_ack_rxbuf(struct hn_rx_ring *,
|
||||
struct vmbus_channel *, uint64_t);
|
||||
|
||||
#if __FreeBSD_version >= 1100099
|
||||
static int hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#endif
|
||||
static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#if __FreeBSD_version < 1100095
|
||||
static int hn_rx_stat_int_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#else
|
||||
static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#endif
|
||||
static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_caps_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rss_hash_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
static void hn_stop(struct hn_softc *);
|
||||
static void hn_init_locked(struct hn_softc *);
|
||||
static int hn_chan_attach(struct hn_softc *,
|
||||
struct vmbus_channel *);
|
||||
static void hn_chan_detach(struct hn_softc *,
|
||||
struct vmbus_channel *);
|
||||
static int hn_attach_subchans(struct hn_softc *);
|
||||
static void hn_detach_allchans(struct hn_softc *);
|
||||
static void hn_chan_rollup(struct hn_rx_ring *,
|
||||
struct hn_tx_ring *);
|
||||
static void hn_set_ring_inuse(struct hn_softc *, int);
|
||||
static int hn_synth_attach(struct hn_softc *, int);
|
||||
static void hn_synth_detach(struct hn_softc *);
|
||||
static int hn_synth_alloc_subchans(struct hn_softc *,
|
||||
int *);
|
||||
static void hn_suspend(struct hn_softc *);
|
||||
static void hn_suspend_data(struct hn_softc *);
|
||||
static void hn_suspend_mgmt(struct hn_softc *);
|
||||
static void hn_resume(struct hn_softc *);
|
||||
static void hn_resume_data(struct hn_softc *);
|
||||
static void hn_resume_mgmt(struct hn_softc *);
|
||||
static void hn_suspend_mgmt_taskfunc(void *, int);
|
||||
static void hn_chan_drain(struct vmbus_channel *);
|
||||
|
||||
static void hn_update_link_status(struct hn_softc *);
|
||||
static void hn_change_network(struct hn_softc *);
|
||||
static void hn_link_taskfunc(void *, int);
|
||||
static void hn_netchg_init_taskfunc(void *, int);
|
||||
static void hn_netchg_status_taskfunc(void *, int);
|
||||
static void hn_link_status(struct hn_softc *);
|
||||
|
||||
static int hn_create_rx_data(struct hn_softc *, int);
|
||||
static void hn_destroy_rx_data(struct hn_softc *);
|
||||
static int hn_check_iplen(const struct mbuf *, int);
|
||||
static int hn_set_rxfilter(struct hn_softc *);
|
||||
static int hn_rss_reconfig(struct hn_softc *);
|
||||
static void hn_rss_ind_fixup(struct hn_softc *, int);
|
||||
static int hn_rxpkt(struct hn_rx_ring *, const void *,
|
||||
int, const struct hn_rxinfo *);
|
||||
|
||||
static int hn_tx_ring_create(struct hn_softc *, int);
|
||||
static void hn_tx_ring_destroy(struct hn_tx_ring *);
|
||||
static int hn_create_tx_data(struct hn_softc *, int);
|
||||
static void hn_fixup_tx_data(struct hn_softc *);
|
||||
static void hn_destroy_tx_data(struct hn_softc *);
|
||||
static void hn_txdesc_dmamap_destroy(struct hn_txdesc *);
|
||||
static int hn_encap(struct hn_tx_ring *,
|
||||
struct hn_txdesc *, struct mbuf **);
|
||||
static int hn_txpkt(struct ifnet *, struct hn_tx_ring *,
|
||||
struct hn_txdesc *);
|
||||
static void hn_set_chim_size(struct hn_softc *, int);
|
||||
static void hn_set_tso_maxsize(struct hn_softc *, int, int);
|
||||
static bool hn_tx_ring_pending(struct hn_tx_ring *);
|
||||
static void hn_tx_ring_qflush(struct hn_tx_ring *);
|
||||
static void hn_resume_tx(struct hn_softc *, int);
|
||||
static int hn_get_txswq_depth(const struct hn_tx_ring *);
|
||||
static void hn_txpkt_done(struct hn_nvs_sendctx *,
|
||||
struct hn_softc *, struct vmbus_channel *,
|
||||
const void *, int);
|
||||
static int hn_txpkt_sglist(struct hn_tx_ring *,
|
||||
struct hn_txdesc *);
|
||||
static int hn_txpkt_chim(struct hn_tx_ring *,
|
||||
struct hn_txdesc *);
|
||||
static int hn_xmit(struct hn_tx_ring *, int);
|
||||
static void hn_xmit_taskfunc(void *, int);
|
||||
static void hn_xmit_txeof(struct hn_tx_ring *);
|
||||
static void hn_xmit_txeof_taskfunc(void *, int);
|
||||
static int hn_start_locked(struct hn_tx_ring *, int);
|
||||
static void hn_start_taskfunc(void *, int);
|
||||
static void hn_start_txeof(struct hn_tx_ring *);
|
||||
static void hn_start_txeof_taskfunc(void *, int);
|
||||
|
||||
SYSCTL_NODE(_hw, OID_AUTO, hn, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
|
||||
"Hyper-V network interface");
|
||||
|
||||
/* Trust tcp segements verification on host side. */
|
||||
static int hn_trust_hosttcp = 1;
|
||||
static int hn_trust_hosttcp = 1;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, trust_hosttcp, CTLFLAG_RDTUN,
|
||||
&hn_trust_hosttcp, 0,
|
||||
"Trust tcp segement verification on host side, "
|
||||
"when csum info is missing (global setting)");
|
||||
|
||||
/* Trust udp datagrams verification on host side. */
|
||||
static int hn_trust_hostudp = 1;
|
||||
static int hn_trust_hostudp = 1;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, trust_hostudp, CTLFLAG_RDTUN,
|
||||
&hn_trust_hostudp, 0,
|
||||
"Trust udp datagram verification on host side, "
|
||||
"when csum info is missing (global setting)");
|
||||
|
||||
/* Trust ip packets verification on host side. */
|
||||
static int hn_trust_hostip = 1;
|
||||
static int hn_trust_hostip = 1;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, trust_hostip, CTLFLAG_RDTUN,
|
||||
&hn_trust_hostip, 0,
|
||||
"Trust ip packet verification on host side, "
|
||||
"when csum info is missing (global setting)");
|
||||
|
||||
/* Limit TSO burst size */
|
||||
static int hn_tso_maxlen = IP_MAXPACKET;
|
||||
static int hn_tso_maxlen = IP_MAXPACKET;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, tso_maxlen, CTLFLAG_RDTUN,
|
||||
&hn_tso_maxlen, 0, "TSO burst limit");
|
||||
|
||||
/* Limit chimney send size */
|
||||
static int hn_tx_chimney_size = 0;
|
||||
static int hn_tx_chimney_size = 0;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, tx_chimney_size, CTLFLAG_RDTUN,
|
||||
&hn_tx_chimney_size, 0, "Chimney send packet size limit");
|
||||
|
||||
/* Limit the size of packet for direct transmission */
|
||||
static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF;
|
||||
static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, direct_tx_size, CTLFLAG_RDTUN,
|
||||
&hn_direct_tx_size, 0, "Size of the packet for direct transmission");
|
||||
|
||||
/* # of LRO entries per RX ring */
|
||||
#if defined(INET) || defined(INET6)
|
||||
#if __FreeBSD_version >= 1100095
|
||||
static int hn_lro_entry_count = HN_LROENT_CNT_DEF;
|
||||
static int hn_lro_entry_count = HN_LROENT_CNT_DEF;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, lro_entry_count, CTLFLAG_RDTUN,
|
||||
&hn_lro_entry_count, 0, "LRO entry count");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int hn_share_tx_taskq = 0;
|
||||
/* Use shared TX taskqueue */
|
||||
static int hn_share_tx_taskq = 0;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, share_tx_taskq, CTLFLAG_RDTUN,
|
||||
&hn_share_tx_taskq, 0, "Enable shared TX taskqueue");
|
||||
|
||||
static struct taskqueue *hn_tx_taskq;
|
||||
|
||||
#ifndef HN_USE_TXDESC_BUFRING
|
||||
static int hn_use_txdesc_bufring = 0;
|
||||
static int hn_use_txdesc_bufring = 0;
|
||||
#else
|
||||
static int hn_use_txdesc_bufring = 1;
|
||||
static int hn_use_txdesc_bufring = 1;
|
||||
#endif
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, use_txdesc_bufring, CTLFLAG_RD,
|
||||
&hn_use_txdesc_bufring, 0, "Use buf_ring for TX descriptors");
|
||||
|
||||
static int hn_bind_tx_taskq = -1;
|
||||
/* Bind TX taskqueue to the target CPU */
|
||||
static int hn_bind_tx_taskq = -1;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, bind_tx_taskq, CTLFLAG_RDTUN,
|
||||
&hn_bind_tx_taskq, 0, "Bind TX taskqueue to the specified cpu");
|
||||
|
||||
static int hn_use_if_start = 0;
|
||||
/* Use ifnet.if_start instead of ifnet.if_transmit */
|
||||
static int hn_use_if_start = 0;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, use_if_start, CTLFLAG_RDTUN,
|
||||
&hn_use_if_start, 0, "Use if_start TX method");
|
||||
|
||||
static int hn_chan_cnt = 0;
|
||||
/* # of channels to use */
|
||||
static int hn_chan_cnt = 0;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, chan_cnt, CTLFLAG_RDTUN,
|
||||
&hn_chan_cnt, 0,
|
||||
"# of channels to use; each channel has one RX ring and one TX ring");
|
||||
|
||||
static int hn_tx_ring_cnt = 0;
|
||||
/* # of transmit rings to use */
|
||||
static int hn_tx_ring_cnt = 0;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, tx_ring_cnt, CTLFLAG_RDTUN,
|
||||
&hn_tx_ring_cnt, 0, "# of TX rings to use");
|
||||
|
||||
static int hn_tx_swq_depth = 0;
|
||||
/* Software TX ring deptch */
|
||||
static int hn_tx_swq_depth = 0;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, tx_swq_depth, CTLFLAG_RDTUN,
|
||||
&hn_tx_swq_depth, 0, "Depth of IFQ or BUFRING");
|
||||
|
||||
/* Enable sorted LRO, and the depth of the per-channel mbuf queue */
|
||||
#if __FreeBSD_version >= 1100095
|
||||
static u_int hn_lro_mbufq_depth = 0;
|
||||
static u_int hn_lro_mbufq_depth = 0;
|
||||
SYSCTL_UINT(_hw_hn, OID_AUTO, lro_mbufq_depth, CTLFLAG_RDTUN,
|
||||
&hn_lro_mbufq_depth, 0, "Depth of LRO mbuf queue");
|
||||
#endif
|
||||
|
||||
static u_int hn_cpu_index;
|
||||
static u_int hn_cpu_index; /* next CPU for channel */
|
||||
static struct taskqueue *hn_tx_taskq; /* shared TX taskqueue */
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
*/
|
||||
static void hn_stop(struct hn_softc *sc);
|
||||
static void hn_init_locked(struct hn_softc *sc);
|
||||
static void hn_init(void *xsc);
|
||||
static int hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
|
||||
static int hn_start_locked(struct hn_tx_ring *txr, int len);
|
||||
static void hn_start(struct ifnet *ifp);
|
||||
static void hn_start_txeof(struct hn_tx_ring *);
|
||||
static int hn_ifmedia_upd(struct ifnet *ifp);
|
||||
static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
|
||||
#if __FreeBSD_version >= 1100099
|
||||
static int hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#endif
|
||||
static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#if __FreeBSD_version < 1100095
|
||||
static int hn_rx_stat_int_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#else
|
||||
static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
#endif
|
||||
static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_caps_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_rss_hash_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int hn_check_iplen(const struct mbuf *, int);
|
||||
static int hn_create_tx_ring(struct hn_softc *, int);
|
||||
static void hn_destroy_tx_ring(struct hn_tx_ring *);
|
||||
static int hn_create_tx_data(struct hn_softc *, int);
|
||||
static void hn_fixup_tx_data(struct hn_softc *);
|
||||
static void hn_destroy_tx_data(struct hn_softc *);
|
||||
static void hn_start_taskfunc(void *, int);
|
||||
static void hn_start_txeof_taskfunc(void *, int);
|
||||
static void hn_link_taskfunc(void *, int);
|
||||
static void hn_netchg_init_taskfunc(void *, int);
|
||||
static void hn_netchg_status_taskfunc(void *, int);
|
||||
static void hn_suspend_mgmt_taskfunc(void *, int);
|
||||
static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **);
|
||||
static int hn_create_rx_data(struct hn_softc *sc, int);
|
||||
static void hn_destroy_rx_data(struct hn_softc *sc);
|
||||
static void hn_set_chim_size(struct hn_softc *, int);
|
||||
static void hn_set_tso_maxsize(struct hn_softc *, int, int);
|
||||
static int hn_chan_attach(struct hn_softc *, struct vmbus_channel *);
|
||||
static void hn_chan_detach(struct hn_softc *, struct vmbus_channel *);
|
||||
static int hn_attach_subchans(struct hn_softc *);
|
||||
static void hn_detach_allchans(struct hn_softc *);
|
||||
static void hn_chan_callback(struct vmbus_channel *chan, void *xrxr);
|
||||
static void hn_chan_rollup(struct hn_rx_ring *, struct hn_tx_ring *);
|
||||
static void hn_set_ring_inuse(struct hn_softc *, int);
|
||||
static int hn_synth_attach(struct hn_softc *, int);
|
||||
static void hn_synth_detach(struct hn_softc *);
|
||||
static bool hn_tx_ring_pending(struct hn_tx_ring *);
|
||||
static void hn_suspend(struct hn_softc *);
|
||||
static void hn_suspend_data(struct hn_softc *);
|
||||
static void hn_suspend_mgmt(struct hn_softc *);
|
||||
static void hn_resume(struct hn_softc *);
|
||||
static void hn_resume_data(struct hn_softc *);
|
||||
static void hn_resume_mgmt(struct hn_softc *);
|
||||
static void hn_rx_drain(struct vmbus_channel *);
|
||||
static void hn_tx_resume(struct hn_softc *, int);
|
||||
static void hn_tx_ring_qflush(struct hn_tx_ring *);
|
||||
static int netvsc_detach(device_t dev);
|
||||
static void hn_link_status(struct hn_softc *);
|
||||
static int hn_sendpkt_rndis_sglist(struct hn_tx_ring *, struct hn_txdesc *);
|
||||
static int hn_sendpkt_rndis_chim(struct hn_tx_ring *, struct hn_txdesc *);
|
||||
static int hn_set_rxfilter(struct hn_softc *);
|
||||
static void hn_link_status_update(struct hn_softc *);
|
||||
static void hn_network_change(struct hn_softc *);
|
||||
|
||||
static int hn_rndis_rxinfo(const void *, int, struct hn_rxinfo *);
|
||||
static void hn_rndis_rx_data(struct hn_rx_ring *, const void *, int);
|
||||
static void hn_rndis_rx_status(struct hn_softc *, const void *, int);
|
||||
|
||||
static void hn_nvs_handle_notify(struct hn_softc *sc,
|
||||
const struct vmbus_chanpkt_hdr *pkt);
|
||||
static void hn_nvs_handle_comp(struct hn_softc *sc, struct vmbus_channel *chan,
|
||||
const struct vmbus_chanpkt_hdr *pkt);
|
||||
static void hn_nvs_handle_rxbuf(struct hn_rx_ring *rxr,
|
||||
struct vmbus_channel *chan,
|
||||
const struct vmbus_chanpkt_hdr *pkthdr);
|
||||
static void hn_nvs_ack_rxbuf(struct hn_rx_ring *, struct vmbus_channel *,
|
||||
uint64_t);
|
||||
|
||||
static int hn_transmit(struct ifnet *, struct mbuf *);
|
||||
static void hn_xmit_qflush(struct ifnet *);
|
||||
static int hn_xmit(struct hn_tx_ring *, int);
|
||||
static void hn_xmit_txeof(struct hn_tx_ring *);
|
||||
static void hn_xmit_taskfunc(void *, int);
|
||||
static void hn_xmit_txeof_taskfunc(void *, int);
|
||||
|
||||
static const uint8_t hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
|
||||
static const uint8_t
|
||||
hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
|
||||
0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
|
||||
0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
|
||||
0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
|
||||
@ -432,6 +434,27 @@ static const uint8_t hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
|
||||
0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
|
||||
};
|
||||
|
||||
static device_method_t hn_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, hn_probe),
|
||||
DEVMETHOD(device_attach, hn_attach),
|
||||
DEVMETHOD(device_detach, hn_detach),
|
||||
DEVMETHOD(device_shutdown, hn_shutdown),
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t hn_driver = {
|
||||
"hn",
|
||||
hn_methods,
|
||||
sizeof(struct hn_softc)
|
||||
};
|
||||
|
||||
static devclass_t hn_devclass;
|
||||
|
||||
DRIVER_MODULE(hn, vmbus, hn_driver, hn_devclass, 0, 0);
|
||||
MODULE_VERSION(hn, 1);
|
||||
MODULE_DEPEND(hn, vmbus, 1, 1, 1);
|
||||
|
||||
#if __FreeBSD_version >= 1100099
|
||||
static void
|
||||
hn_set_lro_lenlim(struct hn_softc *sc, int lenlim)
|
||||
@ -444,7 +467,7 @@ hn_set_lro_lenlim(struct hn_softc *sc, int lenlim)
|
||||
#endif
|
||||
|
||||
static int
|
||||
hn_sendpkt_rndis_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
hn_txpkt_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
{
|
||||
|
||||
KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID &&
|
||||
@ -454,7 +477,7 @@ hn_sendpkt_rndis_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
}
|
||||
|
||||
static int
|
||||
hn_sendpkt_rndis_chim(struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
hn_txpkt_chim(struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
{
|
||||
struct hn_nvs_rndis rndis;
|
||||
|
||||
@ -653,13 +676,10 @@ static const struct hyperv_guid g_net_vsc_device_type = {
|
||||
0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
|
||||
};
|
||||
|
||||
/*
|
||||
* Standard probe entry point.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
netvsc_probe(device_t dev)
|
||||
hn_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (VMBUS_PROBE_GUID(device_get_parent(dev), dev,
|
||||
&g_net_vsc_device_type) == 0) {
|
||||
device_set_desc(dev, "Hyper-V Network Interface");
|
||||
@ -668,14 +688,8 @@ netvsc_probe(device_t dev)
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard attach entry point.
|
||||
*
|
||||
* Called when the driver is loaded. It allocates needed resources,
|
||||
* and initializes the "hardware" and software.
|
||||
*/
|
||||
static int
|
||||
netvsc_attach(device_t dev)
|
||||
hn_attach(device_t dev)
|
||||
{
|
||||
struct hn_softc *sc = device_get_softc(dev);
|
||||
struct sysctl_oid_list *child;
|
||||
@ -917,18 +931,18 @@ netvsc_attach(device_t dev)
|
||||
* Kick off link status check.
|
||||
*/
|
||||
sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0;
|
||||
hn_link_status_update(sc);
|
||||
hn_update_link_status(sc);
|
||||
|
||||
return (0);
|
||||
failed:
|
||||
if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED)
|
||||
hn_synth_detach(sc);
|
||||
netvsc_detach(dev);
|
||||
hn_detach(dev);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
netvsc_detach(device_t dev)
|
||||
hn_detach(device_t dev)
|
||||
{
|
||||
struct hn_softc *sc = device_get_softc(dev);
|
||||
struct ifnet *ifp = sc->hn_ifp;
|
||||
@ -967,12 +981,10 @@ netvsc_detach(device_t dev)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard shutdown entry point
|
||||
*/
|
||||
static int
|
||||
netvsc_shutdown(device_t dev)
|
||||
hn_shutdown(device_t dev)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1037,7 +1049,7 @@ hn_netchg_status_taskfunc(void *xsc, int pending __unused)
|
||||
}
|
||||
|
||||
static void
|
||||
hn_link_status_update(struct hn_softc *sc)
|
||||
hn_update_link_status(struct hn_softc *sc)
|
||||
{
|
||||
|
||||
if (sc->hn_mgmt_taskq != NULL)
|
||||
@ -1045,7 +1057,7 @@ hn_link_status_update(struct hn_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
hn_network_change(struct hn_softc *sc)
|
||||
hn_change_network(struct hn_softc *sc)
|
||||
{
|
||||
|
||||
if (sc->hn_mgmt_taskq != NULL)
|
||||
@ -1197,7 +1209,7 @@ hn_txeof(struct hn_tx_ring *txr)
|
||||
}
|
||||
|
||||
static void
|
||||
hn_tx_done(struct hn_nvs_sendctx *sndc, struct hn_softc *sc,
|
||||
hn_txpkt_done(struct hn_nvs_sendctx *sndc, struct hn_softc *sc,
|
||||
struct vmbus_channel *chan, const void *data __unused, int dlen __unused)
|
||||
{
|
||||
struct hn_txdesc *txd = sndc->hn_cbarg;
|
||||
@ -1420,7 +1432,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
txd->chim_size = pkt->rm_len;
|
||||
txr->hn_gpa_cnt = 0;
|
||||
txr->hn_tx_chimney++;
|
||||
txr->hn_sendpkt = hn_sendpkt_rndis_chim;
|
||||
txr->hn_sendpkt = hn_txpkt_chim;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -1467,12 +1479,12 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
|
||||
txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
|
||||
txd->chim_size = 0;
|
||||
txr->hn_sendpkt = hn_sendpkt_rndis_sglist;
|
||||
txr->hn_sendpkt = hn_txpkt_sglist;
|
||||
done:
|
||||
txd->m = m_head;
|
||||
|
||||
/* Set the completion routine */
|
||||
hn_nvs_sendctx_init(&txd->send_ctx, hn_tx_done, txd);
|
||||
hn_nvs_sendctx_init(&txd->send_ctx, hn_txpkt_done, txd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1483,7 +1495,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
* associated w/ the txd will _not_ be freed.
|
||||
*/
|
||||
static int
|
||||
hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
hn_txpkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
{
|
||||
int error, send_failed = 0;
|
||||
|
||||
@ -1599,7 +1611,7 @@ hn_start_locked(struct hn_tx_ring *txr, int len)
|
||||
continue;
|
||||
}
|
||||
|
||||
error = hn_send_pkt(ifp, txr, txd);
|
||||
error = hn_txpkt(ifp, txr, txd);
|
||||
if (__predict_false(error)) {
|
||||
/* txd is freed, but m_head is not */
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
|
||||
@ -2114,9 +2126,6 @@ hn_stop(struct hn_softc *sc)
|
||||
sc->hn_tx_ring[i].hn_oactive = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FreeBSD transmit entry point
|
||||
*/
|
||||
static void
|
||||
hn_start(struct ifnet *ifp)
|
||||
{
|
||||
@ -2195,7 +2204,7 @@ hn_init_locked(struct hn_softc *sc)
|
||||
sc->hn_tx_ring[i].hn_oactive = 0;
|
||||
|
||||
/* Clear TX 'suspended' bit. */
|
||||
hn_tx_resume(sc, sc->hn_tx_ring_inuse);
|
||||
hn_resume_tx(sc, sc->hn_tx_ring_inuse);
|
||||
|
||||
/* Everything is ready; unleash! */
|
||||
atomic_set_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
|
||||
@ -2211,20 +2220,6 @@ hn_init(void *xsc)
|
||||
HN_UNLOCK(sc);
|
||||
}
|
||||
|
||||
#ifdef LATER
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
hn_watchdog(struct ifnet *ifp)
|
||||
{
|
||||
|
||||
if_printf(ifp, "watchdog timeout -- resetting\n");
|
||||
hn_init(ifp->if_softc); /* XXX */
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __FreeBSD_version >= 1100099
|
||||
|
||||
static int
|
||||
@ -2906,7 +2901,7 @@ hn_destroy_rx_data(struct hn_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
hn_create_tx_ring(struct hn_softc *sc, int id)
|
||||
hn_tx_ring_create(struct hn_softc *sc, int id)
|
||||
{
|
||||
struct hn_tx_ring *txr = &sc->hn_tx_ring[id];
|
||||
device_t dev = sc->hn_dev;
|
||||
@ -3103,7 +3098,7 @@ hn_txdesc_dmamap_destroy(struct hn_txdesc *txd)
|
||||
}
|
||||
|
||||
static void
|
||||
hn_destroy_tx_ring(struct hn_tx_ring *txr)
|
||||
hn_tx_ring_destroy(struct hn_tx_ring *txr)
|
||||
{
|
||||
struct hn_txdesc *txd;
|
||||
|
||||
@ -3179,7 +3174,7 @@ hn_create_tx_data(struct hn_softc *sc, int ring_cnt)
|
||||
for (i = 0; i < sc->hn_tx_ring_cnt; ++i) {
|
||||
int error;
|
||||
|
||||
error = hn_create_tx_ring(sc, i);
|
||||
error = hn_tx_ring_create(sc, i);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
@ -3325,7 +3320,7 @@ hn_destroy_tx_data(struct hn_softc *sc)
|
||||
return;
|
||||
|
||||
for (i = 0; i < sc->hn_tx_ring_cnt; ++i)
|
||||
hn_destroy_tx_ring(&sc->hn_tx_ring[i]);
|
||||
hn_tx_ring_destroy(&sc->hn_tx_ring[i]);
|
||||
|
||||
free(sc->hn_tx_ring, M_DEVBUF);
|
||||
sc->hn_tx_ring = NULL;
|
||||
@ -3401,7 +3396,7 @@ hn_xmit(struct hn_tx_ring *txr, int len)
|
||||
continue;
|
||||
}
|
||||
|
||||
error = hn_send_pkt(ifp, txr, txd);
|
||||
error = hn_txpkt(ifp, txr, txd);
|
||||
if (__predict_false(error)) {
|
||||
/* txd is freed, but m_head is not */
|
||||
drbr_putback(ifp, txr->hn_mbuf_br, m_head);
|
||||
@ -3924,7 +3919,7 @@ hn_set_ring_inuse(struct hn_softc *sc, int ring_cnt)
|
||||
}
|
||||
|
||||
static void
|
||||
hn_rx_drain(struct vmbus_channel *chan)
|
||||
hn_chan_drain(struct vmbus_channel *chan)
|
||||
{
|
||||
|
||||
while (!vmbus_chan_rx_empty(chan) || !vmbus_chan_tx_empty(chan))
|
||||
@ -3979,9 +3974,9 @@ hn_suspend_data(struct hn_softc *sc)
|
||||
|
||||
if (subch != NULL) {
|
||||
for (i = 0; i < nsubch; ++i)
|
||||
hn_rx_drain(subch[i]);
|
||||
hn_chan_drain(subch[i]);
|
||||
}
|
||||
hn_rx_drain(sc->hn_prichan);
|
||||
hn_chan_drain(sc->hn_prichan);
|
||||
|
||||
if (subch != NULL)
|
||||
vmbus_subchan_rel(subch, nsubch);
|
||||
@ -4026,7 +4021,7 @@ hn_suspend(struct hn_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
hn_tx_resume(struct hn_softc *sc, int tx_ring_cnt)
|
||||
hn_resume_tx(struct hn_softc *sc, int tx_ring_cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -4059,7 +4054,7 @@ hn_resume_data(struct hn_softc *sc)
|
||||
* since hn_tx_ring_inuse can be changed after
|
||||
* hn_suspend_data().
|
||||
*/
|
||||
hn_tx_resume(sc, sc->hn_tx_ring_cnt);
|
||||
hn_resume_tx(sc, sc->hn_tx_ring_cnt);
|
||||
|
||||
if (!hn_use_if_start) {
|
||||
/*
|
||||
@ -4097,9 +4092,9 @@ hn_resume_mgmt(struct hn_softc *sc)
|
||||
* detection.
|
||||
*/
|
||||
if (sc->hn_link_flags & HN_LINK_FLAG_NETCHG)
|
||||
hn_network_change(sc);
|
||||
hn_change_network(sc);
|
||||
else
|
||||
hn_link_status_update(sc);
|
||||
hn_update_link_status(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4126,7 +4121,7 @@ hn_rndis_rx_status(struct hn_softc *sc, const void *data, int dlen)
|
||||
switch (msg->rm_status) {
|
||||
case RNDIS_STATUS_MEDIA_CONNECT:
|
||||
case RNDIS_STATUS_MEDIA_DISCONNECT:
|
||||
hn_link_status_update(sc);
|
||||
hn_update_link_status(sc);
|
||||
break;
|
||||
|
||||
case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG:
|
||||
@ -4146,7 +4141,7 @@ hn_rndis_rx_status(struct hn_softc *sc, const void *data, int dlen)
|
||||
if_printf(sc->hn_ifp, "network changed, change %u\n",
|
||||
change);
|
||||
}
|
||||
hn_network_change(sc);
|
||||
hn_change_network(sc);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -4661,25 +4656,3 @@ hn_tx_taskq_destroy(void *arg __unused)
|
||||
}
|
||||
SYSUNINIT(hn_txtq_destroy, SI_SUB_DRIVERS, SI_ORDER_SECOND,
|
||||
hn_tx_taskq_destroy, NULL);
|
||||
|
||||
static device_method_t netvsc_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, netvsc_probe),
|
||||
DEVMETHOD(device_attach, netvsc_attach),
|
||||
DEVMETHOD(device_detach, netvsc_detach),
|
||||
DEVMETHOD(device_shutdown, netvsc_shutdown),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t netvsc_driver = {
|
||||
NETVSC_DEVNAME,
|
||||
netvsc_methods,
|
||||
sizeof(struct hn_softc)
|
||||
};
|
||||
|
||||
static devclass_t netvsc_devclass;
|
||||
|
||||
DRIVER_MODULE(hn, vmbus, netvsc_driver, netvsc_devclass, 0, 0);
|
||||
MODULE_VERSION(hn, 1);
|
||||
MODULE_DEPEND(hn, vmbus, 1, 1, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user