From cb2a10a66c6314051a1092a3dfed8502c579027b Mon Sep 17 00:00:00 2001 From: sephe Date: Wed, 15 Jun 2016 03:48:55 +0000 Subject: [PATCH] MFC 296083,296084,296085,296086,296087,296088,296089 296083 hyperv: Remove useless channel inbound_lock It serves no purpose. Reviewed by: Hongjiang Zhang MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5450 296084 hyperv: Always set device for channels And unregister hv_device only for primary channels, who own the hv_device. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5451 296085 hyperv/hn: Pass channel as the channel callback argument This is the preamble to pass channel back to hn(4) upon TX/RX done. Reviewed by: Hongjiang Zhang MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5452 296086 hyperv/hn: Pass channel to TX/RX done This is preamble to associate the TX/RX rings to their channel. While I'm here, revoke unused netvsc_recv_rollup. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5453 296087 hyperv/hn: Associate TX/RX ring with channel This fixes the TX/RX ring selection for TX/RX done. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5454 296088 hyperv/hn: Remove the useless num_outstanding_sends We rely on taskqueue draining now. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5456 296089 hyperv/hn: Make transmission path channel aware Chimney sending buffer still needs conversion, which will be done along with the upcoming vRSS support. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5457 git-svn-id: svn://svn.freebsd.org/base/stable/10@301912 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/hyperv/include/hyperv.h | 10 +-- sys/dev/hyperv/netvsc/hv_net_vsc.c | 47 +++++--------- sys/dev/hyperv/netvsc/hv_net_vsc.h | 7 ++- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 62 +++++++++---------- sys/dev/hyperv/netvsc/hv_rndis.h | 10 +-- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 40 +++--------- sys/dev/hyperv/netvsc/hv_rndis_filter.h | 7 ++- .../hyperv/storvsc/hv_storvsc_drv_freebsd.c | 11 +--- sys/dev/hyperv/vmbus/hv_channel.c | 13 ---- sys/dev/hyperv/vmbus/hv_channel_mgmt.c | 15 +++-- 10 files changed, 87 insertions(+), 135 deletions(-) diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index f45543bae..376dd5f73 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -753,8 +753,6 @@ typedef struct hv_vmbus_channel { */ hv_vmbus_ring_buffer_info inbound; - struct mtx inbound_lock; - struct taskqueue * rxq; struct task channel_task; hv_vmbus_pfn_channel_callback on_channel_callback; @@ -824,12 +822,16 @@ typedef struct hv_vmbus_channel { * This will be NULL for the primary channel. */ struct hv_vmbus_channel *primary_channel; + /* - * Support per channel state for use by vmbus drivers. + * Driver private data */ - void *per_channel_state; + void *hv_chan_priv1; + void *hv_chan_priv2; } hv_vmbus_channel; +#define HV_VMBUS_CHAN_ISPRIMARY(chan) ((chan)->primary_channel == NULL) + static inline void hv_set_channel_read_state(hv_vmbus_channel* channel, boolean_t state) { diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 9a89b62ef..03cd6d2b6 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -62,7 +62,8 @@ static int hv_nv_connect_to_vsp(struct hv_device *device); static void hv_nv_on_send_completion(netvsc_dev *net_dev, struct hv_device *device, hv_vm_packet_descriptor *pkt); static void hv_nv_on_receive(netvsc_dev *net_dev, - struct hv_device *device, hv_vm_packet_descriptor *pkt); + struct hv_device *device, struct hv_vmbus_channel *chan, + hv_vm_packet_descriptor *pkt); /* * @@ -115,7 +116,7 @@ hv_nv_get_inbound_net_device(struct hv_device *device) * permit incoming packets if and only if there * are outstanding sends. */ - if (net_dev->destroy && net_dev->num_outstanding_sends == 0) { + if (net_dev->destroy) { return (NULL); } @@ -678,7 +679,7 @@ hv_nv_on_device_add(struct hv_device *device, void *additional_info) */ ret = hv_vmbus_channel_open(device->channel, NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, - NULL, 0, hv_nv_on_channel_callback, device); + NULL, 0, hv_nv_on_channel_callback, device->channel); if (ret != 0) goto cleanup; @@ -719,14 +720,7 @@ hv_nv_on_device_remove(struct hv_device *device, boolean_t destroy_channel) netvsc_dev *net_dev = sc->net_dev;; /* Stop outbound traffic ie sends and receives completions */ - mtx_lock(&device->channel->inbound_lock); net_dev->destroy = TRUE; - mtx_unlock(&device->channel->inbound_lock); - - /* Wait for all send completions */ - while (net_dev->num_outstanding_sends) { - DELAY(100); - } hv_nv_disconnect_from_vsp(net_dev); @@ -805,8 +799,6 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, net_vsc_pkt->compl.send.send_completion_context); } - - atomic_subtract_int(&net_dev->num_outstanding_sends, 1); } } @@ -816,16 +808,11 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, * Returns 0 on success, non-zero on failure. */ int -hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt) +hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt) { - netvsc_dev *net_dev; nvsp_msg send_msg; int ret; - net_dev = hv_nv_get_outbound_net_device(device); - if (!net_dev) - return (ENODEV); - send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt; if (pkt->is_data_pkt) { /* 0 is RMC_DATA */ @@ -841,20 +828,16 @@ hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt) pkt->send_buf_section_size; if (pkt->page_buf_count) { - ret = hv_vmbus_channel_send_packet_pagebuffer(device->channel, + ret = hv_vmbus_channel_send_packet_pagebuffer(chan, pkt->page_buffers, pkt->page_buf_count, &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt); } else { - ret = hv_vmbus_channel_send_packet(device->channel, + ret = hv_vmbus_channel_send_packet(chan, &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); } - /* Record outstanding send only if send_packet() succeeded */ - if (ret == 0) - atomic_add_int(&net_dev->num_outstanding_sends, 1); - return (ret); } @@ -866,7 +849,7 @@ hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt) */ static void hv_nv_on_receive(netvsc_dev *net_dev, struct hv_device *device, - hv_vm_packet_descriptor *pkt) + struct hv_vmbus_channel *chan, hv_vm_packet_descriptor *pkt) { hv_vm_transfer_page_packet_header *vm_xfer_page_pkt; nvsp_msg *nvsp_msg_pkt; @@ -916,7 +899,7 @@ hv_nv_on_receive(netvsc_dev *net_dev, struct hv_device *device, net_vsc_pkt->tot_data_buf_len = vm_xfer_page_pkt->ranges[i].byte_count; - hv_rf_on_receive(net_dev, device, net_vsc_pkt); + hv_rf_on_receive(net_dev, device, chan, net_vsc_pkt); if (net_vsc_pkt->status != nvsp_status_success) { status = nvsp_status_failure; } @@ -929,7 +912,6 @@ hv_nv_on_receive(netvsc_dev *net_dev, struct hv_device *device, */ hv_nv_on_receive_completion(device, vm_xfer_page_pkt->d.transaction_id, status); - hv_rf_receive_rollup(net_dev); } /* @@ -973,9 +955,10 @@ hv_nv_on_receive_completion(struct hv_device *device, uint64_t tid, * Net VSC on channel callback */ static void -hv_nv_on_channel_callback(void *context) +hv_nv_on_channel_callback(void *xchan) { - struct hv_device *device = (struct hv_device *)context; + struct hv_vmbus_channel *chan = xchan; + struct hv_device *device = chan->device; netvsc_dev *net_dev; device_t dev = device->device; uint32_t bytes_rxed; @@ -992,7 +975,7 @@ hv_nv_on_channel_callback(void *context) buffer = net_dev->callback_buf; do { - ret = hv_vmbus_channel_recv_packet_raw(device->channel, + ret = hv_vmbus_channel_recv_packet_raw(chan, buffer, bufferlen, &bytes_rxed, &request_id); if (ret == 0) { if (bytes_rxed > 0) { @@ -1002,7 +985,7 @@ hv_nv_on_channel_callback(void *context) hv_nv_on_send_completion(net_dev, device, desc); break; case HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES: - hv_nv_on_receive(net_dev, device, desc); + hv_nv_on_receive(net_dev, device, chan, desc); break; default: device_printf(dev, @@ -1036,5 +1019,5 @@ hv_nv_on_channel_callback(void *context) if (bufferlen > NETVSC_PACKET_SIZE) free(buffer, M_NETVSC); - hv_rf_channel_rollup(net_dev); + hv_rf_channel_rollup(chan); } diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index aba09c067..7d13c7788 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -893,7 +893,6 @@ typedef struct nvsp_msg_ { */ typedef struct netvsc_dev_ { struct hv_device *dev; - int num_outstanding_sends; /* Send buffer allocated by us but manages by NetVSP */ void *send_buf; @@ -1000,6 +999,7 @@ struct buf_ring; #endif struct hn_rx_ring { + struct ifnet *hn_ifp; struct lro_ctrl hn_lro; /* Trust csum verification on host side */ @@ -1017,6 +1017,8 @@ struct hn_rx_ring { #define HN_TRUST_HCSUM_TCP 0x0002 #define HN_TRUST_HCSUM_UDP 0x0004 +struct hv_vmbus_channel; + struct hn_tx_ring { #ifndef HN_USE_TXDESC_BUFRING struct mtx hn_txlist_spin; @@ -1039,6 +1041,7 @@ struct hn_tx_ring { struct mtx hn_tx_lock; struct hn_softc *hn_sc; + struct hv_vmbus_channel *hn_chan; int hn_direct_tx_size; int hn_tx_chimney_size; @@ -1097,7 +1100,7 @@ netvsc_dev *hv_nv_on_device_add(struct hv_device *device, void *additional_info); int hv_nv_on_device_remove(struct hv_device *device, boolean_t destroy_channel); -int hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt); +int hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt); int hv_nv_get_next_send_section(netvsc_dev *net_dev); #endif /* __HV_NET_VSC_H__ */ diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index fcfa1cd86..ec4697d5f 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -119,6 +119,8 @@ __FBSDID("$FreeBSD$"); #include "hv_rndis.h" #include "hv_rndis_filter.h" +#define hv_chan_rxr hv_chan_priv1 +#define hv_chan_txr hv_chan_priv2 /* Short for Hyper-V network interface */ #define NETVSC_DEVNAME "hn" @@ -397,6 +399,7 @@ static int netvsc_attach(device_t dev) { struct hv_device *device_ctx = vmbus_get_devctx(dev); + struct hv_vmbus_channel *chan; netvsc_device_info device_info; hn_softc_t *sc; int unit = device_get_unit(dev); @@ -449,6 +452,14 @@ netvsc_attach(device_t dev) hn_create_rx_data(sc); + /* + * Associate the first TX/RX ring w/ the primary channel. + */ + chan = device_ctx->channel; + chan->hv_chan_rxr = &sc->hn_rx_ring[0]; + chan->hv_chan_txr = &sc->hn_tx_ring[0]; + sc->hn_tx_ring[0].hn_chan = chan; + if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_dunit = unit; ifp->if_dname = NETVSC_DEVNAME; @@ -706,12 +717,11 @@ hn_tx_done(void *xpkt) } void -netvsc_channel_rollup(struct hv_device *device_ctx) +netvsc_channel_rollup(struct hv_vmbus_channel *chan) { - struct hn_softc *sc = device_get_softc(device_ctx->device); - struct hn_tx_ring *txr = &sc->hn_tx_ring[0]; /* TODO: vRSS */ + struct hn_tx_ring *txr = chan->hv_chan_txr; #if defined(INET) || defined(INET6) - struct hn_rx_ring *rxr = &sc->hn_rx_ring[0]; /* TODO: vRSS */ + struct hn_rx_ring *rxr = chan->hv_chan_rxr; struct lro_ctrl *lro = &rxr->hn_lro; struct lro_entry *queued; @@ -721,7 +731,12 @@ netvsc_channel_rollup(struct hv_device *device_ctx) } #endif - if (!txr->hn_has_txeof) + /* + * NOTE: + * 'txr' could be NULL, if multiple channels and + * ifnet.if_start method are enabled. + */ + if (txr == NULL || !txr->hn_has_txeof) return; txr->hn_has_txeof = 0; @@ -862,6 +877,8 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) /* * Chimney send, if the packet could fit into one chimney buffer. + * + * TODO: vRSS, chimney buffer should be per-channel. */ if (packet->tot_data_buf_len < txr->hn_tx_chimney_size) { netvsc_dev *net_dev = txr->hn_sc->net_dev; @@ -948,8 +965,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 hv_device *device_ctx, - struct hn_tx_ring *txr, struct hn_txdesc *txd) +hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd) { int error, send_failed = 0; @@ -958,7 +974,7 @@ hn_send_pkt(struct ifnet *ifp, struct hv_device *device_ctx, * Make sure that txd is not freed before ETHER_BPF_MTAP. */ hn_txdesc_hold(txd); - error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt); + error = hv_nv_on_send(txr->hn_chan, &txd->netvsc_pkt); if (!error) { ETHER_BPF_MTAP(ifp, txd->m); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); @@ -1018,7 +1034,6 @@ hn_start_locked(struct hn_tx_ring *txr, int len) { struct hn_softc *sc = txr->hn_sc; struct ifnet *ifp = sc->hn_ifp; - struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); KASSERT(hn_use_if_start, ("hn_start_locked is called, when if_start is disabled")); @@ -1062,7 +1077,7 @@ hn_start_locked(struct hn_tx_ring *txr, int len) continue; } - error = hn_send_pkt(ifp, device_ctx, txr, txd); + error = hn_send_pkt(ifp, txr, txd); if (__predict_false(error)) { /* txd is freed, but m_head is not */ IFQ_DRV_PREPEND(&ifp->if_snd, m_head); @@ -1157,26 +1172,16 @@ hv_m_append(struct mbuf *m0, int len, c_caddr_t cp) * Note: This is no longer used as a callback */ int -netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, +netvsc_recv(struct hv_vmbus_channel *chan, netvsc_packet *packet, rndis_tcp_ip_csum_info *csum_info) { - struct hn_softc *sc = device_get_softc(device_ctx->device); - struct hn_rx_ring *rxr = &sc->hn_rx_ring[0]; /* TODO: vRSS */ + struct hn_rx_ring *rxr = chan->hv_chan_rxr; + struct ifnet *ifp = rxr->hn_ifp; struct mbuf *m_new; - struct ifnet *ifp; int size, do_lro = 0, do_csum = 1; - if (sc == NULL) { - return (0); /* TODO: KYS how can this be! */ - } - - ifp = sc->hn_ifp; - - ifp = sc->arpcom.ac_ifp; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) return (0); - } /* * Bail out if packet contains more data than configured MTU. @@ -1329,11 +1334,6 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, return (0); } -void -netvsc_recv_rollup(struct hv_device *device_ctx __unused) -{ -} - /* * Rules for using sc->temp_unusable: * 1. sc->temp_unusable can only be read or written while holding NV_LOCK() @@ -2084,6 +2084,7 @@ hn_create_rx_data(struct hn_softc *sc) rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_UDP; if (hn_trust_hostip) rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_IP; + rxr->hn_ifp = sc->hn_ifp; /* * Initialize LRO. @@ -2567,7 +2568,6 @@ hn_xmit(struct hn_tx_ring *txr, int len) { struct hn_softc *sc = txr->hn_sc; struct ifnet *ifp = sc->hn_ifp; - struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); struct mbuf *m_head; mtx_assert(&txr->hn_tx_lock, MA_OWNED); @@ -2606,7 +2606,7 @@ hn_xmit(struct hn_tx_ring *txr, int len) continue; } - error = hn_send_pkt(ifp, device_ctx, txr, txd); + error = hn_send_pkt(ifp, txr, txd); if (__predict_false(error)) { /* txd is freed, but m_head is not */ drbr_putback(ifp, txr->hn_mbuf_br, m_head); diff --git a/sys/dev/hyperv/netvsc/hv_rndis.h b/sys/dev/hyperv/netvsc/hv_rndis.h index cd46ecc3b..44782ecc6 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis.h +++ b/sys/dev/hyperv/netvsc/hv_rndis.h @@ -1046,11 +1046,11 @@ typedef struct rndismp_rx_bufs_info_ { /* * Externs */ -int netvsc_recv(struct hv_device *device_ctx, - netvsc_packet *packet, - rndis_tcp_ip_csum_info *csum_info); -void netvsc_recv_rollup(struct hv_device *device_ctx); -void netvsc_channel_rollup(struct hv_device *device_ctx); +struct hv_vmbus_channel; + +int netvsc_recv(struct hv_vmbus_channel *chan, + netvsc_packet *packet, rndis_tcp_ip_csum_info *csum_info); +void netvsc_channel_rollup(struct hv_vmbus_channel *chan); void* hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size, diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 31ddbc02a..ea140940d 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -59,6 +59,7 @@ static void hv_rf_receive_response(rndis_device *device, rndis_msg *response); static void hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response); static void hv_rf_receive_data(rndis_device *device, rndis_msg *message, + struct hv_vmbus_channel *chan, netvsc_packet *pkt); static int hv_rf_query_device(rndis_device *device, uint32_t oid, void *result, uint32_t *result_size); @@ -250,7 +251,7 @@ hv_rf_send_request(rndis_device *device, rndis_request *request, NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; packet->send_buf_section_size = 0; - ret = hv_nv_on_send(device->net_dev->dev, packet); + ret = hv_nv_on_send(device->net_dev->dev->channel, packet); return (ret); } @@ -406,7 +407,8 @@ hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response) * RNDIS filter receive data */ static void -hv_rf_receive_data(rndis_device *device, rndis_msg *message, netvsc_packet *pkt) +hv_rf_receive_data(rndis_device *device, rndis_msg *message, + struct hv_vmbus_channel *chan, netvsc_packet *pkt) { rndis_packet *rndis_pkt; ndis_8021q_info *rppi_vlan_info; @@ -444,14 +446,15 @@ hv_rf_receive_data(rndis_device *device, rndis_msg *message, netvsc_packet *pkt) } csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info); - netvsc_recv(device->net_dev->dev, pkt, csum_info); + netvsc_recv(chan, pkt, csum_info); } /* * RNDIS filter on receive */ int -hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device, netvsc_packet *pkt) +hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device, + struct hv_vmbus_channel *chan, netvsc_packet *pkt) { rndis_device *rndis_dev; rndis_msg *rndis_hdr; @@ -474,7 +477,7 @@ hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device, netvsc_packet *p /* data message */ case REMOTE_NDIS_PACKET_MSG: - hv_rf_receive_data(rndis_dev, rndis_hdr, pkt); + hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt); break; /* completion messages */ case REMOTE_NDIS_INITIALIZE_CMPLT: @@ -958,32 +961,9 @@ hv_rf_on_send_request_halt_completion(void *context) request->halt_complete_flag = 1; } -/* - * RNDIS filter when "all" reception is done - */ void -hv_rf_receive_rollup(netvsc_dev *net_dev) +hv_rf_channel_rollup(struct hv_vmbus_channel *chan) { - rndis_device *rndis_dev; - - rndis_dev = (rndis_device *)net_dev->extension; - netvsc_recv_rollup(rndis_dev->net_dev->dev); -} -void -hv_rf_channel_rollup(netvsc_dev *net_dev) -{ - rndis_device *rndis_dev; - - rndis_dev = (rndis_device *)net_dev->extension; - - /* - * This could be called pretty early, so we need - * to make sure everything has been setup. - */ - if (rndis_dev == NULL || - rndis_dev->net_dev == NULL || - rndis_dev->net_dev->dev == NULL) - return; - netvsc_channel_rollup(rndis_dev->net_dev->dev); + netvsc_channel_rollup(chan); } diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.h b/sys/dev/hyperv/netvsc/hv_rndis_filter.h index 9d7a38dc1..54dda67bb 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.h +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.h @@ -95,11 +95,12 @@ typedef struct rndis_device_ { /* * Externs */ +struct hv_vmbus_channel; -int hv_rf_on_receive(netvsc_dev *net_dev, - struct hv_device *device, netvsc_packet *pkt); +int hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device, + struct hv_vmbus_channel *chan, netvsc_packet *pkt); void hv_rf_receive_rollup(netvsc_dev *net_dev); -void hv_rf_channel_rollup(netvsc_dev *net_dev); +void hv_rf_channel_rollup(struct hv_vmbus_channel *chan); int hv_rf_on_device_add(struct hv_device *device, void *additl_info); int hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel); int hv_rf_on_open(struct hv_device *device); diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index 27fb3fd59..7e0034bc0 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -365,7 +365,7 @@ storvsc_handle_sc_creation(void *context) int ret = 0; new_channel = (hv_vmbus_channel *)context; - device = new_channel->primary_channel->device; + device = new_channel->device; sc = get_stor_device(device, TRUE); if (sc == NULL) return; @@ -883,12 +883,7 @@ hv_storvsc_on_channel_callback(void *context) struct hv_storvsc_request *request; struct vstor_packet *vstor_packet; - if (channel->primary_channel != NULL){ - device = channel->primary_channel->device; - } else { - device = channel->device; - } - + device = channel->device; KASSERT(device, ("device is NULL")); sc = get_stor_device(device, FALSE); @@ -1186,9 +1181,7 @@ storvsc_detach(device_t dev) struct hv_sgl_node *sgl_node = NULL; int j = 0; - mtx_lock(&hv_device->channel->inbound_lock); sc->hs_destroy = TRUE; - mtx_unlock(&hv_device->channel->inbound_lock); /* * At this point, all outbound traffic should be disabled. We diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c index a9b7bd430..9f9753083 100644 --- a/sys/dev/hyperv/vmbus/hv_channel.c +++ b/sys/dev/hyperv/vmbus/hv_channel.c @@ -537,13 +537,7 @@ hv_vmbus_channel_close_internal(hv_vmbus_channel *channel) */ channel->rxq = NULL; taskqueue_drain(rxq, &channel->channel_task); - /* - * Grab the lock to prevent race condition when a packet received - * and unloading driver is in the process. - */ - mtx_lock(&channel->inbound_lock); channel->on_channel_callback = NULL; - mtx_unlock(&channel->inbound_lock); /** * Send a closing message @@ -920,12 +914,6 @@ VmbusProcessChannelEvent(void* context, int pending) * callback to NULL. This closes the window. */ - /* - * Disable the lock due to newly added WITNESS check in r277723. - * Will seek other way to avoid race condition. - * -- whu - */ - // mtx_lock(&channel->inbound_lock); if (channel->on_channel_callback != NULL) { arg = channel->channel_callback_context; is_batched_reading = channel->batched_reading; @@ -952,5 +940,4 @@ VmbusProcessChannelEvent(void* context, int pending) bytes_to_read = 0; } while (is_batched_reading && (bytes_to_read != 0)); } - // mtx_unlock(&channel->inbound_lock); } diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c index ab6e8ad54..fdd094409 100644 --- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -143,9 +143,7 @@ hv_vmbus_allocate_channel(void) M_DEVBUF, M_WAITOK | M_ZERO); - mtx_init(&channel->inbound_lock, "channel inbound", NULL, MTX_DEF); mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF); - TAILQ_INIT(&channel->sc_list_anchor); return (channel); @@ -158,8 +156,6 @@ void hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel) { mtx_destroy(&channel->sc_lock); - mtx_destroy(&channel->inbound_lock); - free(channel, M_DEVBUF); } @@ -218,6 +214,7 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel) * It is a sub channel offer, process it. */ new_channel->primary_channel = channel; + new_channel->device = channel->device; mtx_lock(&channel->sc_lock); TAILQ_INSERT_TAIL( &channel->sc_list_anchor, @@ -458,7 +455,10 @@ vmbus_channel_on_offer_rescind_internal(void *context) hv_vmbus_channel* channel; channel = (hv_vmbus_channel*)context; - hv_vmbus_child_device_unregister(channel->device); + if (HV_VMBUS_CHAN_ISPRIMARY(channel)) { + /* Only primary channel owns the hv_device */ + hv_vmbus_child_device_unregister(channel->device); + } } /** @@ -679,7 +679,10 @@ hv_vmbus_release_unattached_channels(void) TAILQ_REMOVE(&hv_vmbus_g_connection.channel_anchor, channel, list_entry); - hv_vmbus_child_device_unregister(channel->device); + if (HV_VMBUS_CHAN_ISPRIMARY(channel)) { + /* Only primary channel owns the hv_device */ + hv_vmbus_child_device_unregister(channel->device); + } hv_vmbus_free_vmbus_channel(channel); } bzero(hv_vmbus_g_connection.channels, -- 2.45.0