Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Oct 2016 06:39:06 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r307185 - stable/10/sys/dev/hyperv/netvsc
Message-ID:  <201610130639.u9D6d6OC096379@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Thu Oct 13 06:39:06 2016
New Revision: 307185
URL: https://svnweb.freebsd.org/changeset/base/307185

Log:
  MFC 305049,305050
  
  305049
      hyperv/hn: Factor out func to exec RNDIS transaction w/o checking result
  
      It will be used by RNDIS HALT and RESET.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7685
  
  305050
      hyperv/hn: Switch to new RNDIS transaction execution for halt.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7686

Modified:
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Thu Oct 13 06:34:18 2016	(r307184)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Thu Oct 13 06:39:06 2016	(r307185)
@@ -73,8 +73,6 @@ static void hv_nv_on_receive(struct hn_s
 static void hn_nvs_sent_none(struct hn_send_ctx *sndc,
     struct hn_softc *, struct vmbus_channel *chan,
     const void *, int);
-static void hn_nvs_sent_xact(struct hn_send_ctx *, struct hn_softc *sc,
-    struct vmbus_channel *, const void *, int);
 
 struct hn_send_ctx	hn_send_ctx_none =
     HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL);
@@ -654,7 +652,7 @@ hv_nv_on_device_remove(struct hn_softc *
 	return (0);
 }
 
-static void
+void
 hn_nvs_sent_xact(struct hn_send_ctx *sndc,
     struct hn_softc *sc __unused, struct vmbus_channel *chan __unused,
     const void *data, int dlen)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Oct 13 06:34:18 2016	(r307184)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Oct 13 06:39:06 2016	(r307185)
@@ -72,8 +72,6 @@ __FBSDID("$FreeBSD$");
 /*
  * Forward declarations
  */
-static int  hv_rf_send_request(rndis_device *device, rndis_request *request,
-			       uint32_t message_type);
 static void hv_rf_receive_response(rndis_device *device,
     const rndis_msg *response);
 static void hv_rf_receive_indicate_status(rndis_device *device,
@@ -84,12 +82,6 @@ static inline int hv_rf_query_device_mac
 static inline int hv_rf_query_device_link_status(rndis_device *device);
 static int  hv_rf_init_device(rndis_device *device);
 
-static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
-    struct hn_softc *sc, struct vmbus_channel *chan,
-    const void *data, int dlen);
-static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
-    struct hn_softc *sc, struct vmbus_channel *chan,
-    const void *data, int dlen);
 static int hn_rndis_query(struct hn_softc *sc, uint32_t oid,
     const void *idata, size_t idlen, void *odata, size_t *odlen0);
 static int hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data,
@@ -198,120 +190,6 @@ hv_put_rndis_device(rndis_device *device
 }
 
 /*
- *
- */
-static inline rndis_request *
-hv_rndis_request(rndis_device *device, uint32_t message_type,
-		 uint32_t message_length)
-{
-	rndis_request *request;
-	rndis_msg *rndis_mesg;
-	rndis_set_request *set;
-
-	request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
-
-	sema_init(&request->wait_sema, 0, "rndis sema");
-	
-	rndis_mesg = &request->request_msg;
-	rndis_mesg->ndis_msg_type = message_type;
-	rndis_mesg->msg_len = message_length;
-
-	/*
-	 * Set the request id. This field is always after the rndis header
-	 * for request/response packet types so we just use the set_request
-	 * as a template.
-	 */
-	set = &rndis_mesg->msg.set_request;
-	set->request_id = atomic_fetchadd_int(&device->new_request_id, 1) &
-	    HN_RNDIS_RID_COMPAT_MASK;
-
-	/* Add to the request list */
-	mtx_lock(&device->req_lock);
-	STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
-	mtx_unlock(&device->req_lock);
-
-	return (request);
-}
-
-/*
- *
- */
-static inline void
-hv_put_rndis_request(rndis_device *device, rndis_request *request)
-{
-	mtx_lock(&device->req_lock);
-	/* Fixme:  Has O(n) performance */
-	/*
-	 * XXXKYS: Use Doubly linked lists.
-	 */
-	STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
-	    mylist_entry);
-	mtx_unlock(&device->req_lock);
-
-	sema_destroy(&request->wait_sema);
-	free(request, M_NETVSC);
-}
-
-/*
- *
- */
-static int
-hv_rf_send_request(rndis_device *device, rndis_request *request,
-    uint32_t message_type)
-{
-	struct hn_softc *sc = device->sc;
-	uint32_t send_buf_section_idx, tot_data_buf_len;
-	struct vmbus_gpa gpa[2];
-	int gpa_cnt, send_buf_section_size;
-	hn_sent_callback_t cb;
-
-	/* Set up the packet to send it */
-	tot_data_buf_len = request->request_msg.msg_len;
-
-	gpa_cnt = 1;
-	gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
-	gpa[0].gpa_len = request->request_msg.msg_len;
-	gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
-
-	if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
-		gpa_cnt = 2;
-		gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
-		gpa[1].gpa_page =
-		    hv_get_phys_addr((char*)&request->request_msg +
-		    gpa[0].gpa_len) >> PAGE_SHIFT;
-		gpa[1].gpa_ofs = 0;
-		gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
-	}
-
-	if (message_type != REMOTE_NDIS_HALT_MSG)
-		cb = hn_rndis_sent_cb;
-	else
-		cb = hn_rndis_sent_halt;
-
-	if (tot_data_buf_len < sc->hn_chim_szmax) {
-		send_buf_section_idx = hn_chim_alloc(sc);
-		if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
-			uint8_t *dest = sc->hn_chim +
-				(send_buf_section_idx * sc->hn_chim_szmax);
-
-			memcpy(dest, &request->request_msg, request->request_msg.msg_len);
-			send_buf_section_size = tot_data_buf_len;
-			gpa_cnt = 0;
-			goto sendit;
-		}
-		/* Failed to allocate chimney send buffer; move on */
-	}
-	send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
-	send_buf_section_size = 0;
-
-sendit:
-	hn_send_ctx_init(&request->send_ctx, cb, request,
-	    send_buf_section_idx, send_buf_section_size);
-	return hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
-	    &request->send_ctx, gpa, gpa_cnt);
-}
-
-/*
  * RNDIS filter receive response
  */
 static void 
@@ -603,20 +481,15 @@ static uint8_t netvsc_hash_key[NDIS_HASH
 };
 
 static const void *
-hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
-    size_t reqlen, size_t *comp_len0, uint32_t comp_type)
+hn_rndis_xact_exec1(struct hn_softc *sc, struct vmbus_xact *xact, size_t reqlen,
+    struct hn_send_ctx *sndc, size_t *comp_len)
 {
 	struct vmbus_gpa gpa[HN_XACT_REQ_PGCNT];
-	const struct rndis_comp_hdr *comp;
-	bus_addr_t paddr;
-	size_t comp_len, min_complen = *comp_len0;
 	int gpa_cnt, error;
+	bus_addr_t paddr;
 
-	KASSERT(rid > HN_RNDIS_RID_COMPAT_MAX, ("invalid rid %u\n", rid));
 	KASSERT(reqlen <= HN_XACT_REQ_SIZE && reqlen > 0,
 	    ("invalid request length %zu", reqlen));
-	KASSERT(min_complen >= sizeof(*comp),
-	    ("invalid minimum complete len %zu", min_complen));
 
 	/*
 	 * Setup the SG list.
@@ -645,14 +518,34 @@ hn_rndis_xact_execute(struct hn_softc *s
 	 * message.
 	 */
 	vmbus_xact_activate(xact);
-	error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
-	    &hn_send_ctx_none, gpa, gpa_cnt);
+	error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL, sndc,
+	    gpa, gpa_cnt);
 	if (error) {
 		vmbus_xact_deactivate(xact);
 		if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
 		return (NULL);
 	}
-	comp = vmbus_xact_wait(xact, &comp_len);
+	return (vmbus_xact_wait(xact, comp_len));
+}
+
+static const void *
+hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
+    size_t reqlen, size_t *comp_len0, uint32_t comp_type)
+{
+	const struct rndis_comp_hdr *comp;
+	size_t comp_len, min_complen = *comp_len0;
+
+	KASSERT(rid > HN_RNDIS_RID_COMPAT_MAX, ("invalid rid %u\n", rid));
+	KASSERT(min_complen >= sizeof(*comp),
+	    ("invalid minimum complete len %zu", min_complen));
+
+	/*
+	 * Execute the xact setup by the caller.
+	 */
+	comp = hn_rndis_xact_exec1(sc, xact, reqlen, &hn_send_ctx_none,
+	    &comp_len);
+	if (comp == NULL)
+		return (NULL);
 
 	/*
 	 * Check this RNDIS complete message.
@@ -1038,51 +931,34 @@ done:
 	return (error);
 }
 
-#define HALT_COMPLETION_WAIT_COUNT      25
-
 /*
  * RNDIS filter halt device
  */
 static int
-hv_rf_halt_device(rndis_device *device)
+hv_rf_halt_device(struct hn_softc *sc)
 {
-	rndis_request *request;
-	int i, ret;
-
-	/* Attempt to do a rndis device halt */
-	request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
-	    RNDIS_MESSAGE_SIZE(rndis_halt_request));
-	if (request == NULL) {
-		return (-1);
-	}
-
-	/* initialize "poor man's semaphore" */
-	request->halt_complete_flag = 0;
-
-	ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
-	if (ret != 0) {
-		return (-1);
-	}
+	struct vmbus_xact *xact;
+	struct rndis_halt_req *halt;
+	struct hn_send_ctx sndc;
+	size_t comp_len;
 
-	/*
-	 * Wait for halt response from halt callback.  We must wait for
-	 * the transaction response before freeing the request and other
-	 * resources.
-	 */
-	for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
-		if (request->halt_complete_flag != 0) {
-			break;
-		}
-		DELAY(400);
-	}
-	if (i == 0) {
-		return (-1);
+	xact = vmbus_xact_get(sc->hn_xact, sizeof(*halt));
+	if (xact == NULL) {
+		if_printf(sc->hn_ifp, "no xact for RNDIS halt\n");
+		return (ENXIO);
 	}
+	halt = vmbus_xact_req_data(xact);
+	halt->rm_type = REMOTE_NDIS_HALT_MSG;
+	halt->rm_len = sizeof(*halt);
+	halt->rm_rid = hn_rndis_rid(sc);
+
+	/* No RNDIS completion; rely on NVS message send completion */
+	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+	hn_rndis_xact_exec1(sc, xact, sizeof(*halt), &sndc, &comp_len);
 
-	device->state = RNDIS_DEV_UNINITIALIZED;
-
-	hv_put_rndis_request(device, request);
-
+	vmbus_xact_put(xact);
+	if (bootverbose)
+		if_printf(sc->hn_ifp, "RNDIS halt done\n");
 	return (0);
 }
 
@@ -1252,7 +1128,7 @@ hv_rf_on_device_remove(struct hn_softc *
 	int ret;
 
 	/* Halt and release the rndis device */
-	ret = hv_rf_halt_device(rndis_dev);
+	ret = hv_rf_halt_device(sc);
 
 	sc->rndis_dev = NULL;
 	hv_put_rndis_device(rndis_dev);
@@ -1292,33 +1168,6 @@ hv_rf_on_close(struct hn_softc *sc)
 	return (hn_rndis_set_rxfilter(sc, 0));
 }
 
-static void
-hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc,
-    struct vmbus_channel *chan __unused, const void *data __unused,
-    int dlen __unused)
-{
-	if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
-		hn_chim_free(sc, sndc->hn_chim_idx);
-}
-
-static void
-hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct hn_softc *sc,
-    struct vmbus_channel *chan __unused, const void *data __unused,
-    int dlen __unused)
-{
-	rndis_request *request = sndc->hn_cbarg;
-
-	if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
-		hn_chim_free(sc, sndc->hn_chim_idx);
-
-	/*
-	 * Notify hv_rf_halt_device() about halt completion.
-	 * The halt code must wait for completion before freeing
-	 * the transaction resources.
-	 */
-	request->halt_complete_flag = 1;
-}
-
 void
 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
 {

Modified: stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/if_hnvar.h	Thu Oct 13 06:34:18 2016	(r307184)
+++ stable/10/sys/dev/hyperv/netvsc/if_hnvar.h	Thu Oct 13 06:39:06 2016	(r307185)
@@ -112,6 +112,8 @@ struct vmbus_xact;
 const void	*hn_nvs_xact_execute(struct hn_softc *sc,
 		    struct vmbus_xact *xact, void *req, int reqlen,
 		    size_t *resp_len);
+void		hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct hn_softc *sc,
+		    struct vmbus_channel *chan, const void *data, int dlen);
 uint32_t	hn_chim_alloc(struct hn_softc *sc);
 void		hn_chim_free(struct hn_softc *sc, uint32_t chim_idx);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610130639.u9D6d6OC096379>