Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131575605
D8209.id21224.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D8209.id21224.diff
View Options
Index: sys/dev/hyperv/netvsc/hv_net_vsc.h
===================================================================
--- sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -233,6 +233,10 @@
struct vmbus_xact_ctx *hn_xact;
uint32_t hn_nvs_ver;
+ struct taskqueue *hn_mgmt_taskq;
+ struct taskqueue *hn_mgmt_taskq0;
+ struct task hn_link_task;
+
uint32_t hn_caps; /* HN_CAP_ */
uint32_t hn_flags; /* HN_FLAG_ */
void *hn_rxbuf;
@@ -271,7 +275,6 @@
*/
struct hn_send_ctx;
-void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status);
int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype,
struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt);
Index: sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
===================================================================
--- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -334,6 +334,8 @@
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_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);
@@ -349,6 +351,8 @@
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_rx_drain(struct vmbus_channel *);
static void hn_tx_resume(struct hn_softc *, int);
@@ -518,7 +522,6 @@
struct sysctl_oid_list *child;
struct sysctl_ctx_list *ctx;
uint8_t eaddr[ETHER_ADDR_LEN];
- uint32_t link_status;
struct ifnet *ifp = NULL;
int error, ring_cnt, tx_ring_cnt;
@@ -551,6 +554,15 @@
}
/*
+ * Setup taskqueue for mangement tasks, e.g. link status.
+ */
+ sc->hn_mgmt_taskq0 = taskqueue_create("hn_mgmt", M_WAITOK,
+ taskqueue_thread_enqueue, &sc->hn_mgmt_taskq0);
+ taskqueue_start_threads(&sc->hn_mgmt_taskq0, 1, PI_NET, "%s mgmt",
+ device_get_nameunit(dev));
+ TASK_INIT(&sc->hn_link_task, 0, hn_link_taskfunc, sc);
+
+ /*
* Allocate ifnet and setup its name earlier, so that if_printf
* can be used by functions, which will be called after
* ether_ifattach().
@@ -621,12 +633,6 @@
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;
@@ -736,6 +742,12 @@
/* Inform the upper layer about the long frame support. */
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
+ /*
+ * Kick off link status check.
+ */
+ sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0;
+ hn_link_status_update(sc);
+
return (0);
failed:
if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED)
@@ -755,6 +767,12 @@
if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
hn_stop(sc);
+ /*
+ * NOTE:
+ * hn_stop() only suspends data, so managment
+ * stuffs have to be suspended manually here.
+ */
+ hn_suspend_mgmt(sc);
hn_synth_detach(sc);
}
HN_UNLOCK(sc);
@@ -767,6 +785,7 @@
if (sc->hn_tx_taskq != hn_tx_taskq)
taskqueue_free(sc->hn_tx_taskq);
+ taskqueue_free(sc->hn_mgmt_taskq0);
if (sc->hn_xact != NULL)
vmbus_xact_ctx_destroy(sc->hn_xact);
@@ -786,6 +805,36 @@
return (0);
}
+static void
+hn_link_taskfunc(void *xsc, int pending __unused)
+{
+ struct hn_softc *sc = xsc;
+ struct ifnet *ifp = sc->hn_ifp;
+ uint32_t link_status;
+ int error;
+
+ error = hn_rndis_get_linkstatus(sc, &link_status);
+ if (error) {
+ /* XXX what to do? */
+ return;
+ }
+
+ if (link_status == NDIS_MEDIA_STATE_CONNECTED)
+ sc->hn_carrier = 1;
+ else
+ sc->hn_carrier = 0;
+ if_link_state_change(ifp,
+ sc->hn_carrier ? LINK_STATE_UP : LINK_STATE_DOWN);
+}
+
+void
+hn_link_status_update(struct hn_softc *sc)
+{
+
+ if (sc->hn_mgmt_taskq != NULL)
+ taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_link_task);
+}
+
static __inline int
hn_txdesc_dmamap_load(struct hn_tx_ring *txr, struct hn_txdesc *txd,
struct mbuf **m_head, bus_dma_segment_t *segs, int *nsegs)
@@ -1311,19 +1360,6 @@
}
/*
- * Link up/down notification
- */
-void
-netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status)
-{
- if (status == 1) {
- sc->hn_carrier = 1;
- } else {
- sc->hn_carrier = 0;
- }
-}
-
-/*
* Append the specified data to the indicated mbuf chain,
* Extend the mbuf chain if the new data does not fit in
* existing space.
@@ -1801,9 +1837,9 @@
KASSERT(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED,
("synthetic parts were not attached"));
- /* Clear RUNNING bit _before_ hn_suspend() */
+ /* Clear RUNNING bit _before_ hn_suspend_data() */
atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
- hn_suspend(sc);
+ hn_suspend_data(sc);
/* Clear OACTIVE bit. */
atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
@@ -1896,9 +1932,6 @@
/* Everything is ready; unleash! */
atomic_set_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
-
- /* TODO: check RNDIS link status. */
- if_link_state_change(ifp, LINK_STATE_UP);
}
static void
@@ -3600,7 +3633,7 @@
}
static void
-hn_suspend(struct hn_softc *sc)
+hn_suspend_data(struct hn_softc *sc)
{
struct vmbus_channel **subch = NULL;
int i, nsubch;
@@ -3654,6 +3687,41 @@
}
static void
+hn_suspend_mgmt_taskfunc(void *xsc, int pending __unused)
+{
+
+ ((struct hn_softc *)xsc)->hn_mgmt_taskq = NULL;
+}
+
+static void
+hn_suspend_mgmt(struct hn_softc *sc)
+{
+ struct task task;
+
+ HN_LOCK_ASSERT(sc);
+
+ /*
+ * Make sure that hn_mgmt_taskq0 can nolonger be accessed
+ * through hn_mgmt_taskq.
+ */
+ TASK_INIT(&task, 0, hn_suspend_mgmt_taskfunc, sc);
+ vmbus_chan_run_task(sc->hn_prichan, &task);
+
+ /*
+ * Make sure that all pending management tasks are completed.
+ */
+ taskqueue_drain_all(sc->hn_mgmt_taskq0);
+}
+
+static void
+hn_suspend(struct hn_softc *sc)
+{
+
+ hn_suspend_data(sc);
+ hn_suspend_mgmt(sc);
+}
+
+static void
hn_tx_resume(struct hn_softc *sc, int tx_ring_cnt)
{
int i;
@@ -3685,7 +3753,8 @@
/*
* Make sure to clear suspend status on "all" TX rings,
- * since hn_tx_ring_inuse can be changed after hn_suspend().
+ * since hn_tx_ring_inuse can be changed after
+ * hn_suspend_data().
*/
hn_tx_resume(sc, sc->hn_tx_ring_cnt);
@@ -3710,6 +3779,12 @@
*/
taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_txeof_task);
}
+
+ /*
+ * Kick off link status check.
+ */
+ sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0;
+ hn_link_status_update(sc);
}
static void
Index: sys/dev/hyperv/netvsc/hv_rndis_filter.c
===================================================================
--- sys/dev/hyperv/netvsc/hv_rndis_filter.c
+++ sys/dev/hyperv/netvsc/hv_rndis_filter.c
@@ -167,11 +167,8 @@
switch (msg->rm_status) {
case RNDIS_STATUS_MEDIA_CONNECT:
- netvsc_linkstatus_callback(sc, 1);
- break;
-
case RNDIS_STATUS_MEDIA_DISCONNECT:
- netvsc_linkstatus_callback(sc, 0);
+ hn_link_status_update(sc);
break;
case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG:
Index: sys/dev/hyperv/netvsc/if_hnvar.h
===================================================================
--- sys/dev/hyperv/netvsc/if_hnvar.h
+++ sys/dev/hyperv/netvsc/if_hnvar.h
@@ -138,6 +138,7 @@
int hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen,
const struct hn_recvinfo *info);
void hn_chan_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr);
+void hn_link_status_update(struct hn_softc *sc);
extern struct hn_send_ctx hn_send_ctx_none;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 10, 10:21 AM (20 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23527627
Default Alt Text
D8209.id21224.diff (7 KB)
Attached To
Mode
D8209: hyperv/hn: Rework link status support.
Attached
Detach File
Event Timeline
Log In to Comment