Index: head/sys/dev/hyperv/include/hyperv.h =================================================================== --- head/sys/dev/hyperv/include/hyperv.h +++ head/sys/dev/hyperv/include/hyperv.h @@ -168,13 +168,6 @@ TAILQ_ENTRY(hv_vmbus_channel) ch_sublink; /* sub-channel link */ struct hv_vmbus_channel *ch_prichan; /* owner primary chan */ - /* - * Driver private data - */ - void *ch_dev_priv1; - void *ch_dev_priv2; - void *ch_dev_priv3; - void *ch_bufring; /* TX+RX bufrings */ struct hyperv_dma ch_bufring_dma; uint32_t ch_bufring_gpadl; Index: head/sys/dev/hyperv/netvsc/hv_net_vsc.h =================================================================== --- head/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1151,8 +1151,12 @@ struct buf_ring; #endif +struct hn_tx_ring; + struct hn_rx_ring { struct ifnet *hn_ifp; + struct hn_tx_ring *hn_txr; + void *hn_rdbuf; int hn_rx_idx; /* Trust csum verification on host side */ @@ -1266,12 +1270,13 @@ void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status); netvsc_dev *hv_nv_on_device_add(struct hn_softc *sc, - void *additional_info); + void *additional_info, struct hn_rx_ring *rxr); int hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel); int hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt); int hv_nv_get_next_send_section(netvsc_dev *net_dev); -void hv_nv_subchan_attach(struct hv_vmbus_channel *chan); +void hv_nv_subchan_attach(struct hv_vmbus_channel *chan, + struct hn_rx_ring *rxr); #endif /* __HV_NET_VSC_H__ */ Index: head/sys/dev/hyperv/netvsc/hv_net_vsc.c =================================================================== --- head/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -49,15 +49,13 @@ #include "hv_rndis.h" #include "hv_rndis_filter.h" -/* priv1 and priv2 are consumed by the main driver */ -#define ch_dev_rdbuf ch_dev_priv3 - MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver"); /* * Forward declarations */ -static void hv_nv_on_channel_callback(struct hv_vmbus_channel *chan, void *arg); +static void hv_nv_on_channel_callback(struct hv_vmbus_channel *chan, + void *xrxr); static int hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc); static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *); static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev); @@ -68,7 +66,7 @@ static void hv_nv_on_receive_completion(struct hv_vmbus_channel *chan, uint64_t tid, uint32_t status); static void hv_nv_on_receive(netvsc_dev *net_dev, - struct hn_softc *sc, struct hv_vmbus_channel *chan, + struct hn_rx_ring *rxr, struct hv_vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkt); /* @@ -641,13 +639,14 @@ } void -hv_nv_subchan_attach(struct hv_vmbus_channel *chan) +hv_nv_subchan_attach(struct hv_vmbus_channel *chan, struct hn_rx_ring *rxr) { - - chan->ch_dev_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); + KASSERT(rxr->hn_rx_idx == chan->ch_subidx, + ("chan%u subidx %u, rxr%d mismatch", + chan->ch_id, chan->ch_subidx, rxr->hn_rx_idx)); vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, - hv_nv_on_channel_callback, NULL); + hv_nv_on_channel_callback, rxr); } /* @@ -656,7 +655,8 @@ * Callback when the device belonging to this driver is added */ netvsc_dev * -hv_nv_on_device_add(struct hn_softc *sc, void *additional_info) +hv_nv_on_device_add(struct hn_softc *sc, void *additional_info, + struct hn_rx_ring *rxr) { struct hv_vmbus_channel *chan = sc->hn_prichan; netvsc_dev *net_dev; @@ -670,18 +670,17 @@ sema_init(&net_dev->channel_init_sema, 0, "netdev_sema"); - chan->ch_dev_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); - /* * Open the channel */ + KASSERT(rxr->hn_rx_idx == chan->ch_subidx, + ("chan%u subidx %u, rxr%d mismatch", + chan->ch_id, chan->ch_subidx, rxr->hn_rx_idx)); ret = vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, - NULL, 0, hv_nv_on_channel_callback, NULL); - if (ret != 0) { - free(chan->ch_dev_rdbuf, M_NETVSC); + NULL, 0, hv_nv_on_channel_callback, rxr); + if (ret != 0) goto cleanup; - } /* * Connect with the NetVsp @@ -694,7 +693,6 @@ close: /* Now, we can close the channel safely */ - free(chan->ch_dev_rdbuf, M_NETVSC); vmbus_chan_close(chan); cleanup: @@ -725,7 +723,6 @@ /* Now, we can close the channel safely */ - free(sc->hn_prichan->ch_dev_rdbuf, M_NETVSC); vmbus_chan_close(sc->hn_prichan); sema_destroy(&net_dev->channel_init_sema); @@ -840,14 +837,13 @@ * with virtual addresses. */ static void -hv_nv_on_receive(netvsc_dev *net_dev, struct hn_softc *sc, +hv_nv_on_receive(netvsc_dev *net_dev, struct hn_rx_ring *rxr, struct hv_vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) { const struct vmbus_chanpkt_rxbuf *pkt; const nvsp_msg *nvsp_msg_pkt; netvsc_packet vsc_pkt; netvsc_packet *net_vsc_pkt = &vsc_pkt; - device_t dev = sc->hn_dev; int count = 0; int i = 0; int status = nvsp_status_success; @@ -856,7 +852,7 @@ /* Make sure this is a valid nvsp packet */ if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) { - device_printf(dev, "packet hdr type %u is invalid!\n", + if_printf(rxr->hn_ifp, "packet hdr type %u is invalid!\n", nvsp_msg_pkt->hdr.msg_type); return; } @@ -864,7 +860,7 @@ pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) { - device_printf(dev, "rxbuf_id %d is invalid!\n", + if_printf(rxr->hn_ifp, "rxbuf_id %d is invalid!\n", pkt->cp_rxbuf_id); return; } @@ -878,7 +874,7 @@ pkt->cp_rxbuf[i].rb_ofs); net_vsc_pkt->tot_data_buf_len = pkt->cp_rxbuf[i].rb_len; - hv_rf_on_receive(net_dev, chan, net_vsc_pkt); + hv_rf_on_receive(net_dev, rxr, net_vsc_pkt); if (net_vsc_pkt->status != nvsp_status_success) { status = nvsp_status_failure; } @@ -973,10 +969,10 @@ * Net VSC on channel callback */ static void -hv_nv_on_channel_callback(struct hv_vmbus_channel *chan, void *arg __unused) +hv_nv_on_channel_callback(struct hv_vmbus_channel *chan, void *xrxr) { - device_t dev = chan->ch_dev; - struct hn_softc *sc = device_get_softc(dev); + struct hn_rx_ring *rxr = xrxr; + struct hn_softc *sc = rxr->hn_ifp->if_softc; netvsc_dev *net_dev; void *buffer; int bufferlen = NETVSC_PACKET_SIZE; @@ -985,7 +981,7 @@ if (net_dev == NULL) return; - buffer = chan->ch_dev_rdbuf; + buffer = rxr->hn_rdbuf; do { struct vmbus_chanpkt_hdr *pkt = buffer; uint32_t bytes_rxed; @@ -1001,13 +997,13 @@ pkt); break; case VMBUS_CHANPKT_TYPE_RXBUF: - hv_nv_on_receive(net_dev, sc, chan, pkt); + hv_nv_on_receive(net_dev, rxr, chan, pkt); break; case VMBUS_CHANPKT_TYPE_INBAND: hv_nv_send_table(sc, pkt); break; default: - device_printf(dev, + if_printf(rxr->hn_ifp, "unknown chan pkt %u\n", pkt->cph_type); break; @@ -1023,7 +1019,7 @@ /* alloc new buffer */ buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT); if (buffer == NULL) { - device_printf(dev, + if_printf(rxr->hn_ifp, "hv_cb malloc buffer failed, len=%u\n", bytes_rxed); bufferlen = 0; @@ -1039,5 +1035,5 @@ if (bufferlen > NETVSC_PACKET_SIZE) free(buffer, M_NETVSC); - hv_rf_channel_rollup(chan); + hv_rf_channel_rollup(rxr, rxr->hn_txr); } Index: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c =================================================================== --- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -120,9 +120,6 @@ #include "hv_rndis_filter.h" #include "vmbus_if.h" -#define ch_dev_rxr ch_dev_priv1 -#define ch_dev_txr ch_dev_priv2 - /* Short for Hyper-V network interface */ #define NETVSC_DEVNAME "hn" @@ -544,7 +541,8 @@ IFCAP_LRO; ifp->if_hwassist = sc->hn_tx_ring[0].hn_csum_assist | CSUM_TSO; - error = hv_rf_on_device_add(sc, &device_info, ring_cnt); + error = hv_rf_on_device_add(sc, &device_info, ring_cnt, + &sc->hn_rx_ring[0]); if (error) goto failed; KASSERT(sc->net_dev->num_channel > 0 && @@ -809,12 +807,9 @@ } void -netvsc_channel_rollup(struct hv_vmbus_channel *chan) +netvsc_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) { - struct hn_tx_ring *txr = chan->ch_dev_txr; #if defined(INET) || defined(INET6) - struct hn_rx_ring *rxr = chan->ch_dev_rxr; - tcp_lro_flush_all(&rxr->hn_lro); #endif @@ -1279,12 +1274,11 @@ * Note: This is no longer used as a callback */ int -netvsc_recv(struct hv_vmbus_channel *chan, netvsc_packet *packet, +netvsc_recv(struct hn_rx_ring *rxr, netvsc_packet *packet, const rndis_tcp_ip_csum_info *csum_info, const struct rndis_hash_info *hash_info, const struct rndis_hash_value *hash_value) { - struct hn_rx_ring *rxr = chan->ch_dev_rxr; struct ifnet *ifp = rxr->hn_ifp; struct mbuf *m_new; int size, do_lro = 0, do_csum = 1; @@ -1589,7 +1583,7 @@ vmbus_subchan_drain(sc->hn_prichan); error = hv_rf_on_device_add(sc, &device_info, - sc->hn_rx_ring_inuse); + sc->hn_rx_ring_inuse, &sc->hn_rx_ring[0]); if (error) { NV_LOCK(sc); sc->temp_unusable = FALSE; @@ -2223,6 +2217,9 @@ if (hn_trust_hostip) rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_IP; rxr->hn_ifp = sc->hn_ifp; + if (i < sc->hn_tx_ring_cnt) + rxr->hn_txr = &sc->hn_tx_ring[i]; + rxr->hn_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); rxr->hn_rx_idx = i; /* @@ -2335,17 +2332,19 @@ static void hn_destroy_rx_data(struct hn_softc *sc) { -#if defined(INET) || defined(INET6) int i; -#endif if (sc->hn_rx_ring_cnt == 0) return; + for (i = 0; i < sc->hn_rx_ring_cnt; ++i) { + struct hn_rx_ring *rxr = &sc->hn_rx_ring[i]; + #if defined(INET) || defined(INET6) - for (i = 0; i < sc->hn_rx_ring_cnt; ++i) - tcp_lro_free(&sc->hn_rx_ring[i].hn_lro); + tcp_lro_free(&rxr->hn_lro); #endif + free(rxr->hn_rdbuf, M_NETVSC); + } free(sc->hn_rx_ring, M_NETVSC); sc->hn_rx_ring = NULL; @@ -2928,7 +2927,6 @@ ("RX ring %d already attached", idx)); rxr->hn_rx_flags |= HN_RX_FLAG_ATTACHED; - chan->ch_dev_rxr = rxr; if (bootverbose) { if_printf(sc->hn_ifp, "link RX ring %d to channel%u\n", idx, chan->ch_id); @@ -2941,7 +2939,6 @@ ("TX ring %d already attached", idx)); txr->hn_tx_flags |= HN_TX_FLAG_ATTACHED; - chan->ch_dev_txr = txr; txr->hn_chan = chan; if (bootverbose) { if_printf(sc->hn_ifp, "link TX ring %d to channel%u\n", @@ -2968,22 +2965,25 @@ static void hn_subchan_setup(struct hn_softc *sc) { - struct hv_vmbus_channel **subchan; + struct hv_vmbus_channel **subchans; int subchan_cnt = sc->net_dev->num_channel - 1; int i; /* Wait for sub-channels setup to complete. */ - subchan = vmbus_subchan_get(sc->hn_prichan, subchan_cnt); + subchans = vmbus_subchan_get(sc->hn_prichan, subchan_cnt); /* Attach the sub-channels. */ for (i = 0; i < subchan_cnt; ++i) { + struct hv_vmbus_channel *subchan = subchans[i]; + /* NOTE: Calling order is critical. */ - hn_subchan_attach(sc, subchan[i]); - hv_nv_subchan_attach(subchan[i]); + hn_subchan_attach(sc, subchan); + hv_nv_subchan_attach(subchan, + &sc->hn_rx_ring[subchan->ch_subidx]); } /* Release the sub-channels */ - vmbus_subchan_rel(subchan, subchan_cnt); + vmbus_subchan_rel(subchans, subchan_cnt); if_printf(sc->hn_ifp, "%d sub-channels setup done\n", subchan_cnt); } Index: head/sys/dev/hyperv/netvsc/hv_rndis.h =================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis.h +++ head/sys/dev/hyperv/netvsc/hv_rndis.h @@ -1083,12 +1083,14 @@ * Externs */ struct hv_vmbus_channel; +struct hn_rx_ring; +struct hn_tx_ring; -int netvsc_recv(struct hv_vmbus_channel *chan, +int netvsc_recv(struct hn_rx_ring *rxr, netvsc_packet *packet, const rndis_tcp_ip_csum_info *csum_info, const struct rndis_hash_info *hash_info, const struct rndis_hash_value *hash_value); -void netvsc_channel_rollup(struct hv_vmbus_channel *chan); +void netvsc_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); void* hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size, Index: head/sys/dev/hyperv/netvsc/hv_rndis_filter.h =================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis_filter.h +++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.h @@ -113,12 +113,14 @@ */ struct hv_vmbus_channel; struct hn_softc; +struct hn_rx_ring; int hv_rf_on_receive(netvsc_dev *net_dev, - struct hv_vmbus_channel *chan, netvsc_packet *pkt); + struct hn_rx_ring *rxr, netvsc_packet *pkt); void hv_rf_receive_rollup(netvsc_dev *net_dev); -void hv_rf_channel_rollup(struct hv_vmbus_channel *chan); -int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int nchan); +void hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); +int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int nchan, + struct hn_rx_ring *rxr); int hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel); int hv_rf_on_open(struct hn_softc *sc); int hv_rf_on_close(struct hn_softc *sc); Index: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c =================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -34,7 +34,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -74,8 +76,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, +static void hv_rf_receive_data(struct hn_rx_ring *rxr, rndis_msg *message, netvsc_packet *pkt); static int hv_rf_query_device(rndis_device *device, uint32_t oid, void *result, uint32_t *result_size); @@ -527,12 +528,11 @@ * RNDIS filter receive data */ static void -hv_rf_receive_data(rndis_device *device, rndis_msg *message, - struct hv_vmbus_channel *chan, netvsc_packet *pkt) +hv_rf_receive_data(struct hn_rx_ring *rxr, rndis_msg *message, + netvsc_packet *pkt) { rndis_packet *rndis_pkt; uint32_t data_offset; - device_t dev = device->net_dev->sc->hn_dev; struct hv_rf_recvinfo info; rndis_pkt = &message->msg.packet; @@ -548,7 +548,7 @@ pkt->tot_data_buf_len -= data_offset; if (pkt->tot_data_buf_len < rndis_pkt->data_length) { pkt->status = nvsp_status_failure; - device_printf(dev, + if_printf(rxr->hn_ifp, "total length %u is less than data length %u\n", pkt->tot_data_buf_len, rndis_pkt->data_length); return; @@ -559,7 +559,7 @@ if (hv_rf_find_recvinfo(rndis_pkt, &info)) { pkt->status = nvsp_status_failure; - device_printf(dev, "recvinfo parsing failed\n"); + if_printf(rxr->hn_ifp, "recvinfo parsing failed\n"); return; } @@ -568,7 +568,7 @@ else pkt->vlan_tci = 0; - netvsc_recv(chan, pkt, info.csum_info, info.hash_info, info.hash_value); + netvsc_recv(rxr, pkt, info.csum_info, info.hash_info, info.hash_value); } /* @@ -576,7 +576,7 @@ */ int hv_rf_on_receive(netvsc_dev *net_dev, - struct hv_vmbus_channel *chan, netvsc_packet *pkt) + struct hn_rx_ring *rxr, netvsc_packet *pkt) { rndis_device *rndis_dev; rndis_msg *rndis_hdr; @@ -599,7 +599,7 @@ /* data message */ case REMOTE_NDIS_PACKET_MSG: - hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt); + hv_rf_receive_data(rxr, rndis_hdr, pkt); break; /* completion messages */ case REMOTE_NDIS_INITIALIZE_CMPLT: @@ -1058,7 +1058,7 @@ */ int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, - int nchan) + int nchan, struct hn_rx_ring *rxr) { int ret; netvsc_dev *net_dev; @@ -1081,7 +1081,7 @@ * (hv_rf_on_receive()) before this call is completed. * Note: Earlier code used a function pointer here. */ - net_dev = hv_nv_on_device_add(sc, additl_info); + net_dev = hv_nv_on_device_add(sc, additl_info, rxr); if (!net_dev) { hv_put_rndis_device(rndis_dev); @@ -1266,8 +1266,8 @@ } void -hv_rf_channel_rollup(struct hv_vmbus_channel *chan) +hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) { - netvsc_channel_rollup(chan); + netvsc_channel_rollup(rxr, txr); }