BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
        BT_DBG("Length\t\t : %d bytes", length);
 
+       config->dnld_mode = ROME_SKIP_EVT_NONE;
+
        switch (config->type) {
        case TLV_TYPE_PATCH:
                tlv_patch = (struct tlv_type_patch *)tlv->data;
-               BT_DBG("Total Length\t\t : %d bytes",
+
+               /* For Rome version 1.1 to 3.1, all segment commands
+                * are acked by a vendor specific event (VSE).
+                * For Rome >= 3.2, the download mode field indicates
+                * if VSE is skipped by the controller.
+                * In case VSE is skipped, only the last segment is acked.
+                */
+               config->dnld_mode = tlv_patch->download_mode;
+
+               BT_DBG("Total Length           : %d bytes",
                       le32_to_cpu(tlv_patch->total_size));
-               BT_DBG("Patch Data Length\t : %d bytes",
+               BT_DBG("Patch Data Length      : %d bytes",
                       le32_to_cpu(tlv_patch->data_length));
                BT_DBG("Signing Format Version : 0x%x",
                       tlv_patch->format_version);
-               BT_DBG("Signature Algorithm\t : 0x%x",
+               BT_DBG("Signature Algorithm    : 0x%x",
                       tlv_patch->signature);
-               BT_DBG("Reserved\t\t : 0x%x",
-                      le16_to_cpu(tlv_patch->reserved1));
-               BT_DBG("Product ID\t\t : 0x%04x",
+               BT_DBG("Download mode          : 0x%x",
+                      tlv_patch->download_mode);
+               BT_DBG("Reserved               : 0x%x",
+                      tlv_patch->reserved1);
+               BT_DBG("Product ID             : 0x%04x",
                       le16_to_cpu(tlv_patch->product_id));
-               BT_DBG("Rom Build Version\t : 0x%04x",
+               BT_DBG("Rom Build Version      : 0x%04x",
                       le16_to_cpu(tlv_patch->rom_build));
-               BT_DBG("Patch Version\t\t : 0x%04x",
+               BT_DBG("Patch Version          : 0x%04x",
                       le16_to_cpu(tlv_patch->patch_version));
-               BT_DBG("Reserved\t\t : 0x%x",
+               BT_DBG("Reserved               : 0x%x",
                       le16_to_cpu(tlv_patch->reserved2));
-               BT_DBG("Patch Entry Address\t : 0x%x",
+               BT_DBG("Patch Entry Address    : 0x%x",
                       le32_to_cpu(tlv_patch->entry));
                break;
 
        }
 }
 
-static int rome_tlv_send_segment(struct hci_dev *hdev, int idx, int seg_size,
-                                const u8 *data)
+static int rome_tlv_send_segment(struct hci_dev *hdev, int seg_size,
+                                const u8 *data, enum rome_tlv_dnld_mode mode)
 {
        struct sk_buff *skb;
        struct edl_event_hdr *edl;
        u8 cmd[MAX_SIZE_PER_TLV_SEGMENT + 2];
        int err = 0;
 
-       BT_DBG("%s: Download segment #%d size %d", hdev->name, idx, seg_size);
-
        cmd[0] = EDL_PATCH_TLV_REQ_CMD;
        cmd[1] = seg_size;
        memcpy(cmd + 2, data, seg_size);
 
+       if (mode == ROME_SKIP_EVT_VSE_CC || mode == ROME_SKIP_EVT_VSE)
+               return __hci_cmd_send(hdev, EDL_PATCH_CMD_OPCODE, seg_size + 2,
+                                     cmd);
+
        skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, seg_size + 2, cmd,
                                HCI_VENDOR_PKT, HCI_INIT_TIMEOUT);
        if (IS_ERR(skb)) {
        return err;
 }
 
-static int rome_tlv_download_request(struct hci_dev *hdev,
-                                    const struct firmware *fw)
-{
-       const u8 *buffer, *data;
-       int total_segment, remain_size;
-       int ret, i;
-
-       if (!fw || !fw->data)
-               return -EINVAL;
-
-       total_segment = fw->size / MAX_SIZE_PER_TLV_SEGMENT;
-       remain_size = fw->size % MAX_SIZE_PER_TLV_SEGMENT;
-
-       BT_DBG("%s: Total segment num %d remain size %d total size %zu",
-              hdev->name, total_segment, remain_size, fw->size);
-
-       data = fw->data;
-       for (i = 0; i < total_segment; i++) {
-               buffer = data + i * MAX_SIZE_PER_TLV_SEGMENT;
-               ret = rome_tlv_send_segment(hdev, i, MAX_SIZE_PER_TLV_SEGMENT,
-                                           buffer);
-               if (ret < 0)
-                       return -EIO;
-       }
-
-       if (remain_size) {
-               buffer = data + total_segment * MAX_SIZE_PER_TLV_SEGMENT;
-               ret = rome_tlv_send_segment(hdev, total_segment, remain_size,
-                                           buffer);
-               if (ret < 0)
-                       return -EIO;
-       }
-
-       return 0;
-}
-
 static int rome_download_firmware(struct hci_dev *hdev,
                                  struct rome_config *config)
 {
        const struct firmware *fw;
-       int ret;
+       const u8 *segment;
+       int ret, remain, i = 0;
 
        bt_dev_info(hdev, "ROME Downloading %s", config->fwname);
 
 
        rome_tlv_check_data(config, fw);
 
-       ret = rome_tlv_download_request(hdev, fw);
-       if (ret) {
-               BT_ERR("%s: Failed to download file: %s (%d)", hdev->name,
-                      config->fwname, ret);
+       segment = fw->data;
+       remain = fw->size;
+       while (remain > 0) {
+               int segsize = min(MAX_SIZE_PER_TLV_SEGMENT, remain);
+
+               bt_dev_dbg(hdev, "Send segment %d, size %d", i++, segsize);
+
+               remain -= segsize;
+               /* The last segment is always acked regardless download mode */
+               if (!remain || segsize < MAX_SIZE_PER_TLV_SEGMENT)
+                       config->dnld_mode = ROME_SKIP_EVT_NONE;
+
+               ret = rome_tlv_send_segment(hdev, segsize, segment,
+                                           config->dnld_mode);
+               if (ret)
+                       break;
+
+               segment += segsize;
        }
 
        release_firmware(fw);