]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/hv/channel_mgmt.c
net: fec: call dma_mapping_error() where appropriate
[karo-tx-linux.git] / drivers / hv / channel_mgmt.c
index 0df75908200e034044ee36fa3fb5403a39fc5efd..fa920469bf104fda2e57d9c2bce2f15f90d5b2a4 100644 (file)
@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry {
  * @negop is of type &struct icmsg_negotiate.
  * Set up and fill in default negotiate response message.
  *
- * The max_fw_version specifies the maximum framework version that
- * we can support and max _srv_version specifies the maximum service
- * version we can support. A special value MAX_SRV_VER can be
- * specified to indicate that we can handle the maximum version
- * exposed by the host.
+ * The fw_version specifies the  framework version that
+ * we can support and srv_version specifies the service
+ * version we can support.
  *
  * Mainly used by Hyper-V drivers.
  */
-void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
+bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
                                struct icmsg_negotiate *negop, u8 *buf,
-                               int max_fw_version, int max_srv_version)
+                               int fw_version, int srv_version)
 {
-       int icframe_vercnt;
-       int icmsg_vercnt;
+       int icframe_major, icframe_minor;
+       int icmsg_major, icmsg_minor;
+       int fw_major, fw_minor;
+       int srv_major, srv_minor;
        int i;
+       bool found_match = false;
 
        icmsghdrp->icmsgsize = 0x10;
+       fw_major = (fw_version >> 16);
+       fw_minor = (fw_version & 0xFFFF);
+
+       srv_major = (srv_version >> 16);
+       srv_minor = (srv_version & 0xFFFF);
 
        negop = (struct icmsg_negotiate *)&buf[
                sizeof(struct vmbuspipe_hdr) +
                sizeof(struct icmsg_hdr)];
 
-       icframe_vercnt = negop->icframe_vercnt;
-       icmsg_vercnt = negop->icmsg_vercnt;
+       icframe_major = negop->icframe_vercnt;
+       icframe_minor = 0;
+
+       icmsg_major = negop->icmsg_vercnt;
+       icmsg_minor = 0;
 
        /*
         * Select the framework version number we will
@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
         */
 
        for (i = 0; i < negop->icframe_vercnt; i++) {
-               if (negop->icversion_data[i].major <= max_fw_version)
-                       icframe_vercnt = negop->icversion_data[i].major;
+               if ((negop->icversion_data[i].major == fw_major) &&
+                  (negop->icversion_data[i].minor == fw_minor)) {
+                       icframe_major = negop->icversion_data[i].major;
+                       icframe_minor = negop->icversion_data[i].minor;
+                       found_match = true;
+               }
        }
 
+       if (!found_match)
+               goto fw_error;
+
+       found_match = false;
+
        for (i = negop->icframe_vercnt;
                 (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
-               if (negop->icversion_data[i].major <= max_srv_version)
-                       icmsg_vercnt = negop->icversion_data[i].major;
+               if ((negop->icversion_data[i].major == srv_major) &&
+                  (negop->icversion_data[i].minor == srv_minor)) {
+                       icmsg_major = negop->icversion_data[i].major;
+                       icmsg_minor = negop->icversion_data[i].minor;
+                       found_match = true;
+               }
        }
 
        /*
-        * Respond with the maximum framework and service
+        * Respond with the framework and service
         * version numbers we can support.
         */
-       negop->icframe_vercnt = 1;
-       negop->icmsg_vercnt = 1;
-       negop->icversion_data[0].major = icframe_vercnt;
-       negop->icversion_data[0].minor = 0;
-       negop->icversion_data[1].major = icmsg_vercnt;
-       negop->icversion_data[1].minor = 0;
+
+fw_error:
+       if (!found_match) {
+               negop->icframe_vercnt = 0;
+               negop->icmsg_vercnt = 0;
+       } else {
+               negop->icframe_vercnt = 1;
+               negop->icmsg_vercnt = 1;
+       }
+
+       negop->icversion_data[0].major = icframe_major;
+       negop->icversion_data[0].minor = icframe_minor;
+       negop->icversion_data[1].major = icmsg_major;
+       negop->icversion_data[1].minor = icmsg_minor;
+       return found_match;
 }
 
 EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
@@ -172,7 +203,8 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
        struct vmbus_channel *primary_channel;
        struct vmbus_channel_relid_released msg;
 
-       vmbus_device_unregister(channel->device_obj);
+       if (channel->device_obj)
+               vmbus_device_unregister(channel->device_obj);
        memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
        msg.child_relid = channel->offermsg.child_relid;
        msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
@@ -185,7 +217,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
        } else {
                primary_channel = channel->primary_channel;
                spin_lock_irqsave(&primary_channel->sc_lock, flags);
-               list_del(&channel->listentry);
+               list_del(&channel->sc_list);
                spin_unlock_irqrestore(&primary_channel->sc_lock, flags);
        }
        free_channel(channel);
@@ -261,6 +293,13 @@ static void vmbus_process_offer(struct work_struct *work)
                return;
        }
 
+       /*
+        * This state is used to indicate a successful open
+        * so that when we do close the channel normally, we
+        * can cleanup properly
+        */
+       newchannel->state = CHANNEL_OPEN_STATE;
+
        /*
         * Start the process of binding this offer to the driver
         * We need to set the DeviceObject field before calling
@@ -287,13 +326,6 @@ static void vmbus_process_offer(struct work_struct *work)
                kfree(newchannel->device_obj);
 
                free_channel(newchannel);
-       } else {
-               /*
-                * This state is used to indicate a successful open
-                * so that when we do close the channel normally, we
-                * can cleanup properly
-                */
-               newchannel->state = CHANNEL_OPEN_STATE;
        }
 }