usb: dwc_otg_310: support vbus controlled by both gpio and pmic
[firefly-linux-kernel-4.4.55.git] / drivers / hv / hv_kvp.c
index 74c38a9f34a609369fc84b9e0c5ce4a4c7de5931..ce4d3a9354916225079f5b12dbf179c6835ffa56 100644 (file)
@@ -66,7 +66,6 @@ static struct {
        struct hv_kvp_msg  *kvp_msg; /* current message */
        struct vmbus_channel *recv_channel; /* chn we got the request */
        u64 recv_req_id; /* request ID. */
-       void *kvp_context; /* for the channel callback */
 } kvp_transaction;
 
 /*
@@ -87,6 +86,7 @@ static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
 static const char kvp_devname[] = "vmbus/hv_kvp";
 static u8 *recv_buffer;
 static struct hvutil_transport *hvt;
+static struct completion release_event;
 /*
  * Register the kernel component with the user-level daemon.
  * As part of this registration, pass the LIC version number.
@@ -94,6 +94,13 @@ static struct hvutil_transport *hvt;
  */
 #define HV_DRV_VERSION           "3.1"
 
+static void kvp_poll_wrapper(void *channel)
+{
+       /* Transaction is finished, reset the state here to avoid races. */
+       kvp_transaction.state = HVUTIL_READY;
+       hv_kvp_onchannelcallback(channel);
+}
+
 static void
 kvp_register(int reg_value)
 {
@@ -121,12 +128,7 @@ static void kvp_timeout_func(struct work_struct *dummy)
         */
        kvp_respond_to_host(NULL, HV_E_FAIL);
 
-       /* Transaction is finished, reset the state. */
-       if (kvp_transaction.state > HVUTIL_READY)
-               kvp_transaction.state = HVUTIL_READY;
-
-       hv_poll_channel(kvp_transaction.kvp_context,
-                       hv_kvp_onchannelcallback);
+       hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
 }
 
 static int kvp_handle_handshake(struct hv_kvp_msg *msg)
@@ -218,9 +220,7 @@ static int kvp_on_msg(void *msg, int len)
         */
        if (cancel_delayed_work_sync(&kvp_timeout_work)) {
                kvp_respond_to_host(message, error);
-               kvp_transaction.state = HVUTIL_READY;
-               hv_poll_channel(kvp_transaction.kvp_context,
-                               hv_kvp_onchannelcallback);
+               hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
        }
 
        return 0;
@@ -596,15 +596,8 @@ void hv_kvp_onchannelcallback(void *context)
        int util_fw_version;
        int kvp_srv_version;
 
-       if (kvp_transaction.state > HVUTIL_READY) {
-               /*
-                * We will defer processing this callback once
-                * the current transaction is complete.
-                */
-               kvp_transaction.kvp_context = context;
+       if (kvp_transaction.state > HVUTIL_READY)
                return;
-       }
-       kvp_transaction.kvp_context = NULL;
 
        vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen,
                         &requestid);
@@ -668,7 +661,8 @@ void hv_kvp_onchannelcallback(void *context)
                         * user-mode not responding.
                         */
                        schedule_work(&kvp_sendkey_work);
-                       schedule_delayed_work(&kvp_timeout_work, 5*HZ);
+                       schedule_delayed_work(&kvp_timeout_work,
+                                             HV_UTIL_TIMEOUT * HZ);
 
                        return;
 
@@ -689,6 +683,7 @@ static void kvp_on_reset(void)
        if (cancel_delayed_work_sync(&kvp_timeout_work))
                kvp_respond_to_host(NULL, HV_E_FAIL);
        kvp_transaction.state = HVUTIL_DEVICE_INIT;
+       complete(&release_event);
 }
 
 int
@@ -696,6 +691,7 @@ hv_kvp_init(struct hv_util_service *srv)
 {
        recv_buffer = srv->recv_buffer;
 
+       init_completion(&release_event);
        /*
         * When this driver loads, the user level daemon that
         * processes the host requests may not yet be running.
@@ -718,4 +714,5 @@ void hv_kvp_deinit(void)
        cancel_delayed_work_sync(&kvp_timeout_work);
        cancel_work_sync(&kvp_sendkey_work);
        hvutil_transport_destroy(hvt);
+       wait_for_completion(&release_event);
 }