summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-10-17 08:53:12 +0000
committersephe <sephe@FreeBSD.org>2016-10-17 08:53:12 +0000
commit34045fe13ec84892dd8ab16b0963b87a5a0248c2 (patch)
tree6aa8a7bae18d652c990c97f30b411d7c61ab73b0 /sys
parent3028da5c260ddfc35e8253f1338823e1211e3869 (diff)
downloadFreeBSD-src-34045fe13ec84892dd8ab16b0963b87a5a0248c2.zip
FreeBSD-src-34045fe13ec84892dd8ab16b0963b87a5a0248c2.tar.gz
MFC 305801,305923,305924
305801 hyperv/hn: Fix some ifnet settings - ifnet.if_mtu does not require explicit setting. - ifnet.if_hdrlen must be set after ether_ifattach(). Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7873 305923 hyperv/hn: Regroup ifnet setup code. While I'm here, add comment along the attach DEVMETHOD. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7874 305924 hyperv/hn: Put debug message under bootverbose Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7875
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c115
1 files changed, 70 insertions, 45 deletions
diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
index 5b61348..fe68872 100644
--- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -456,6 +456,9 @@ netvsc_attach(device_t dev)
sc->hn_prichan = vmbus_get_channel(dev);
HN_LOCK_INIT(sc);
+ /*
+ * Setup taskqueue for transmission.
+ */
if (hn_tx_taskq == NULL) {
sc->hn_tx_taskq = taskqueue_create("hn_tx", M_WAITOK,
taskqueue_thread_enqueue, &sc->hn_tx_taskq);
@@ -477,11 +480,22 @@ netvsc_attach(device_t dev)
sc->hn_tx_taskq = hn_tx_taskq;
}
+ /*
+ * Allocate ifnet and setup its name earlier, so that if_printf
+ * can be used by functions, which will be called after
+ * ether_ifattach().
+ */
ifp = sc->hn_ifp = if_alloc(IFT_ETHER);
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
/*
+ * Initialize ifmedia earlier so that it can be unconditionally
+ * destroyed, if error happened later on.
+ */
+ ifmedia_init(&sc->hn_media, 0, hn_ifmedia_upd, hn_ifmedia_sts);
+
+ /*
* Figure out the # of RX rings (ring_cnt) and the # of TX rings
* to use (tx_ring_cnt).
*
@@ -511,6 +525,10 @@ netvsc_attach(device_t dev)
*/
sc->hn_cpu = atomic_fetchadd_int(&hn_cpu_index, ring_cnt) % mp_ncpus;
+ /*
+ * Create enough TX/RX rings, even if only limited number of
+ * channels can be allocated.
+ */
error = hn_create_tx_data(sc, tx_ring_cnt);
if (error)
goto failed;
@@ -533,10 +551,54 @@ netvsc_attach(device_t dev)
if (error)
goto failed;
+ error = hn_rndis_get_linkstatus(sc, &link_status);
+ if (error)
+ goto failed;
+ if (link_status == NDIS_MEDIA_STATE_CONNECTED)
+ sc->hn_carrier = 1;
+
+ error = hn_rndis_get_eaddr(sc, eaddr);
+ if (error)
+ goto failed;
+
+#if __FreeBSD_version >= 1100099
+ if (sc->hn_rx_ring_inuse > 1) {
+ /*
+ * Reduce TCP segment aggregation limit for multiple
+ * RX rings to increase ACK timeliness.
+ */
+ hn_set_lro_lenlim(sc, HN_LRO_LENLIM_MULTIRX_DEF);
+ }
+#endif
+
+ hn_set_chim_size(sc, sc->hn_chim_szmax);
+ if (hn_tx_chimney_size > 0 &&
+ hn_tx_chimney_size < sc->hn_chim_szmax)
+ hn_set_chim_size(sc, hn_tx_chimney_size);
+
+ ctx = device_get_sysctl_ctx(dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "nvs_version", CTLFLAG_RD,
+ &sc->hn_nvs_ver, 0, "NVS version");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "ndis_version",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
+ hn_ndis_version_sysctl, "A", "NDIS version");
+
+ /*
+ * Setup the ifmedia, which has been initialized earlier.
+ */
+ ifmedia_add(&sc->hn_media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->hn_media, IFM_ETHER | IFM_AUTO);
+ /* XXX ifmedia_set really should do this for us */
+ sc->hn_media.ifm_media = sc->hn_media.ifm_cur->ifm_media;
+
+ /*
+ * Setup the ifnet for this interface.
+ */
+
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = hn_ioctl;
ifp->if_init = hn_init;
- ifp->if_mtu = ETHERMTU;
if (hn_use_if_start) {
int qdepth = hn_get_txswq_depth(&sc->hn_tx_ring[0]);
@@ -549,16 +611,6 @@ netvsc_attach(device_t dev)
ifp->if_qflush = hn_xmit_qflush;
}
- ifmedia_init(&sc->hn_media, 0, hn_ifmedia_upd, hn_ifmedia_sts);
- ifmedia_add(&sc->hn_media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&sc->hn_media, IFM_ETHER | IFM_AUTO);
- /* XXX ifmedia_set really should do this for us */
- sc->hn_media.ifm_media = sc->hn_media.ifm_cur->ifm_media;
-
- /*
- * Tell upper layers that we support full VLAN capability.
- */
- ifp->if_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |=
IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_TSO |
IFCAP_LRO;
@@ -567,54 +619,27 @@ netvsc_attach(device_t dev)
IFCAP_LRO;
ifp->if_hwassist = sc->hn_tx_ring[0].hn_csum_assist | CSUM_TSO;
-#if __FreeBSD_version >= 1100099
- if (sc->hn_rx_ring_inuse > 1) {
- /*
- * Reduce TCP segment aggregation limit for multiple
- * RX rings to increase ACK timeliness.
- */
- hn_set_lro_lenlim(sc, HN_LRO_LENLIM_MULTIRX_DEF);
- }
-#endif
-
- error = hn_rndis_get_linkstatus(sc, &link_status);
- if (error)
- goto failed;
- if (link_status == NDIS_MEDIA_STATE_CONNECTED)
- sc->hn_carrier = 1;
-
tso_maxlen = hn_tso_maxlen;
if (tso_maxlen <= 0 || tso_maxlen > IP_MAXPACKET)
tso_maxlen = IP_MAXPACKET;
-
ifp->if_hw_tsomaxsegcount = HN_TX_DATA_SEGCNT_MAX;
ifp->if_hw_tsomaxsegsize = PAGE_SIZE;
ifp->if_hw_tsomax = tso_maxlen -
(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
- error = hn_rndis_get_eaddr(sc, eaddr);
- if (error)
- goto failed;
ether_ifattach(ifp, eaddr);
- if_printf(ifp, "TSO: %u/%u/%u\n", ifp->if_hw_tsomax,
- ifp->if_hw_tsomaxsegcount, ifp->if_hw_tsomaxsegsize);
-
- hn_set_chim_size(sc, sc->hn_chim_szmax);
- if (hn_tx_chimney_size > 0 &&
- hn_tx_chimney_size < sc->hn_chim_szmax)
- hn_set_chim_size(sc, hn_tx_chimney_size);
+ if (bootverbose) {
+ if_printf(ifp, "TSO: %u/%u/%u\n", ifp->if_hw_tsomax,
+ ifp->if_hw_tsomaxsegcount, ifp->if_hw_tsomaxsegsize);
+ }
- ctx = device_get_sysctl_ctx(dev);
- child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "nvs_version", CTLFLAG_RD,
- &sc->hn_nvs_ver, 0, "NVS version");
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "ndis_version",
- CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
- hn_ndis_version_sysctl, "A", "NDIS version");
+ /* Inform the upper layer about the long frame support. */
+ ifp->if_hdrlen = sizeof(struct ether_vlan_header);
return (0);
failed:
+ /* TODO: reuse netvsc_detach() */
hn_destroy_tx_data(sc);
if (ifp != NULL)
if_free(ifp);
OpenPOWER on IntegriCloud