Esempio n. 1
0
/*
 * Function to read the kvp request buffer from host
 * and interact with daemon
 */
static void
hv_kvp_process_request(void *context, int pending)
{
	uint8_t *kvp_buf;
	hv_vmbus_channel *channel;
	uint32_t recvlen = 0;
	uint64_t requestid;
	struct hv_vmbus_icmsg_hdr *icmsghdrp;
	int ret = 0;
	hv_kvp_sc		*sc;

	hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);

	sc = (hv_kvp_sc*)context;
	kvp_buf = sc->util_sc.receive_buffer;
	channel = sc->util_sc.hv_dev->channel;

	ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
		&recvlen, &requestid);

	while ((ret == 0) && (recvlen > 0)) {

		icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
			&kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];

		hv_kvp_transaction_init(sc, recvlen, requestid, kvp_buf);
		if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
			hv_kvp_negotiate_version(icmsghdrp, NULL, kvp_buf);
			hv_kvp_respond_host(sc, ret);

			/*
			 * It is ok to not acquire the mutex before setting
			 * req_in_progress here because negotiation is the
			 * first thing that happens and hence there is no
			 * chance of a race condition.
			 */

			sc->req_in_progress = false;
			hv_kvp_log_info("%s :version negotiated\n", __func__);

		} else {
			if (!sc->daemon_busy) {

				hv_kvp_log_info("%s: issuing qury to daemon\n", __func__);
				mtx_lock(&sc->pending_mutex);
				sc->req_timed_out = false;
				sc->daemon_busy = true;
				mtx_unlock(&sc->pending_mutex);

				hv_kvp_send_msg_to_daemon(sc);
				hv_kvp_log_info("%s: waiting for daemon\n", __func__);
			}

			/* Wait 5 seconds for daemon to respond back */
			tsleep(sc, 0, "kvpworkitem", 5 * hz);
			hv_kvp_log_info("%s: came out of wait\n", __func__);
		}

		mtx_lock(&sc->pending_mutex);

		/* Notice that once req_timed_out is set to true
		 * it will remain true until the next request is
		 * sent to the daemon. The response from daemon
		 * is forwarded to host only when this flag is
		 * false.
		 */
		sc->req_timed_out = true;

		/*
		 * Cancel request if so need be.
		 */
		if (hv_kvp_req_in_progress(sc)) {
			hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__);
			hv_kvp_respond_host(sc, HV_KVP_E_FAIL);
			sc->req_in_progress = false;
		}

		mtx_unlock(&sc->pending_mutex);

		/*
		 * Try reading next buffer
		 */
		recvlen = 0;
		ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
			&recvlen, &requestid);
		hv_kvp_log_info("%s: read: context %p, ret =%d, recvlen=%d\n",
			__func__, context, ret, recvlen);
	}
}
Esempio n. 2
0
/*
 * Function to read the kvp request buffer from host
 * and interact with daemon
 */
static void
hv_kvp_process_request(void *context)
{
	uint8_t *kvp_buf;
	hv_vmbus_channel *channel = context;
	uint32_t recvlen = 0;
	uint64_t requestid;
	struct hv_vmbus_icmsg_hdr *icmsghdrp;
	int ret = 0;
	uint64_t pending_cnt = 1;
	
	hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);
	kvp_buf = receive_buffer[HV_KVP];
	ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
		&recvlen, &requestid);

	/*
	 * We start counting only after the daemon registers
	 * and therefore there could be requests pending in 
	 * the VMBus that are not reflected in pending_cnt.
	 * Therefore we continue reading as long as either of
	 * the below conditions is true.
	 */

	while ((pending_cnt>0) || ((ret == 0) && (recvlen > 0))) {

		if ((ret == 0) && (recvlen>0)) {
			
			icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
					&kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
	
			hv_kvp_transaction_init(recvlen, channel, requestid, kvp_buf);
			if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
				hv_kvp_negotiate_version(icmsghdrp, NULL, kvp_buf);
				hv_kvp_respond_host(ret);
					
				/*
				 * It is ok to not acquire the mutex before setting 
				 * req_in_progress here because negotiation is the
				 * first thing that happens and hence there is no
				 * chance of a race condition.
				 */
				
				kvp_globals.req_in_progress = false;
				hv_kvp_log_info("%s :version negotiated\n", __func__);

			} else {
				if (!kvp_globals.daemon_busy) {

					hv_kvp_log_info("%s: issuing qury to daemon\n", __func__);
					mtx_lock(&kvp_globals.pending_mutex);
					kvp_globals.req_timed_out = false;
					kvp_globals.daemon_busy = true;
					mtx_unlock(&kvp_globals.pending_mutex);

					hv_kvp_send_msg_to_daemon();
					hv_kvp_log_info("%s: waiting for daemon\n", __func__);
				}
				
				/* Wait 5 seconds for daemon to respond back */
				tsleep(&kvp_globals, 0, "kvpworkitem", 5 * hz);
				hv_kvp_log_info("%s: came out of wait\n", __func__);
			}
		}

		mtx_lock(&kvp_globals.pending_mutex);
		
		/* Notice that once req_timed_out is set to true
		 * it will remain true until the next request is
		 * sent to the daemon. The response from daemon
		 * is forwarded to host only when this flag is 
		 * false. 
		 */
		kvp_globals.req_timed_out = true;

		/*
		 * Cancel request if so need be.
		 */
		if (hv_kvp_req_in_progress()) {
			hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__);
			hv_kvp_respond_host(HV_KVP_E_FAIL);
			kvp_globals.req_in_progress = false;	
		}
	
		/*
		* Decrement pending request count and
		*/
		if (kvp_globals.pending_reqs>0) {
			kvp_globals.pending_reqs = kvp_globals.pending_reqs - 1;
		}
		pending_cnt = kvp_globals.pending_reqs;
		
		mtx_unlock(&kvp_globals.pending_mutex);

		/*
		 * Try reading next buffer
		 */
		recvlen = 0;
		ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
			&recvlen, &requestid);
		hv_kvp_log_info("%s: read: context %p, pending_cnt %ju ret =%d, recvlen=%d\n",
			__func__, context, pending_cnt, ret, recvlen);
	} 
}
Esempio n. 3
0
/*
 * Function to read the kvp request buffer from host
 * and interact with daemon
 */
static void
hv_kvp_process_request(void *context, int pending)
{
	uint8_t *kvp_buf;
	struct vmbus_channel *channel;
	uint32_t recvlen = 0;
	uint64_t requestid;
	struct hv_vmbus_icmsg_hdr *icmsghdrp;
	int ret = 0, error;
	hv_kvp_sc *sc;

	hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);

	sc = (hv_kvp_sc*)context;
	kvp_buf = sc->util_sc.ic_buf;
	channel = vmbus_get_channel(sc->dev);

	recvlen = sc->util_sc.ic_buflen;
	ret = vmbus_chan_recv(channel, kvp_buf, &recvlen, &requestid);
	KASSERT(ret != ENOBUFS, ("hvkvp recvbuf is not large enough"));
	/* XXX check recvlen to make sure that it contains enough data */

	while ((ret == 0) && (recvlen > 0)) {
		icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
		    &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];

		hv_kvp_transaction_init(sc, recvlen, requestid, kvp_buf);
		if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
			error = vmbus_ic_negomsg(&sc->util_sc,
			    kvp_buf, &recvlen, KVP_FWVER, KVP_MSGVER);
			/* XXX handle vmbus_ic_negomsg failure. */
			if (!error)
				hv_kvp_respond_host(sc, HV_S_OK);
			else
				hv_kvp_respond_host(sc, HV_E_FAIL);
			/*
			 * It is ok to not acquire the mutex before setting
			 * req_in_progress here because negotiation is the
			 * first thing that happens and hence there is no
			 * chance of a race condition.
			 */

			sc->req_in_progress = false;
			hv_kvp_log_info("%s :version negotiated\n", __func__);

		} else {
			if (!sc->daemon_busy) {

				hv_kvp_log_info("%s: issuing qury to daemon\n", __func__);
				mtx_lock(&sc->pending_mutex);
				sc->req_timed_out = false;
				sc->daemon_busy = true;
				mtx_unlock(&sc->pending_mutex);

				hv_kvp_send_msg_to_daemon(sc);
				hv_kvp_log_info("%s: waiting for daemon\n", __func__);
			}

			/* Wait 5 seconds for daemon to respond back */
			tsleep(sc, 0, "kvpworkitem", 5 * hz);
			hv_kvp_log_info("%s: came out of wait\n", __func__);
		}

		mtx_lock(&sc->pending_mutex);

		/* Notice that once req_timed_out is set to true
		 * it will remain true until the next request is
		 * sent to the daemon. The response from daemon
		 * is forwarded to host only when this flag is
		 * false.
		 */
		sc->req_timed_out = true;

		/*
		 * Cancel request if so need be.
		 */
		if (hv_kvp_req_in_progress(sc)) {
			hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__);
			hv_kvp_respond_host(sc, HV_E_FAIL);
			sc->req_in_progress = false;
		}

		mtx_unlock(&sc->pending_mutex);

		/*
		 * Try reading next buffer
		 */
		recvlen = sc->util_sc.ic_buflen;
		ret = vmbus_chan_recv(channel, kvp_buf, &recvlen, &requestid);
		KASSERT(ret != ENOBUFS, ("hvkvp recvbuf is not large enough"));
		/* XXX check recvlen to make sure that it contains enough data */

		hv_kvp_log_info("%s: read: context %p, ret =%d, recvlen=%d\n",
			__func__, context, ret, recvlen);
	}
}