Pull char/misc driver fixes from Greg KH: "Here are 4 patches to resolve some char/misc driver issues found these past weeks. One of them is a mei bugfix and another is a new mei device id. There is also a hyper-v fix for a reported issue, and a binder issue fix for a problem reported by a few people. All of these have been in my tree for a while, I don't know if linux-next is really testing much this month. But 0-day is happy with them :)" * tag 'char-misc-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: binder: fix use-after-free in binder_transaction() Drivers: hv: vmbus: Fix bugs in rescind handling mei: me: add gemini lake devices id mei: always use domain runtime pm callbacks.
Unified · Split
| @@ -2582,6 +2582,48 @@ static bool binder_proc_transaction(struct binder_transaction *t, · 2581 unmodified lines | ||
| 2582 | 2582 | return true; |
| 2583 | 2583 | } |
| 2584 | 2584 | |
| 2585 | +/** | |
| 2586 | + * binder_get_node_refs_for_txn() - Get required refs on node for txn | |
| 2587 | + * @node: struct binder_node for which to get refs | |
| 2588 | + * @proc: returns @node->proc if valid | |
| 2589 | + * @error: if no @proc then returns BR_DEAD_REPLY | |
| 2590 | + * | |
| 2591 | + * User-space normally keeps the node alive when creating a transaction | |
| 2592 | + * since it has a reference to the target. The local strong ref keeps it | |
| 2593 | + * alive if the sending process dies before the target process processes | |
| 2594 | + * the transaction. If the source process is malicious or has a reference | |
| 2595 | + * counting bug, relying on the local strong ref can fail. | |
| 2596 | + * | |
| 2597 | + * Since user-space can cause the local strong ref to go away, we also take | |
| 2598 | + * a tmpref on the node to ensure it survives while we are constructing | |
| 2599 | + * the transaction. We also need a tmpref on the proc while we are | |
| 2600 | + * constructing the transaction, so we take that here as well. | |
| 2601 | + * | |
| 2602 | + * Return: The target_node with refs taken or NULL if no @node->proc is NULL. | |
| 2603 | + * Also sets @proc if valid. If the @node->proc is NULL indicating that the | |
| 2604 | + * target proc has died, @error is set to BR_DEAD_REPLY | |
| 2605 | + */ | |
| 2606 | +static struct binder_node *binder_get_node_refs_for_txn( | |
| 2607 | + struct binder_node *node, | |
| 2608 | + struct binder_proc **procp, | |
| 2609 | + uint32_t *error) | |
| 2610 | +{ | |
| 2611 | + struct binder_node *target_node = NULL; | |
| 2612 | + | |
| 2613 | + binder_node_inner_lock(node); | |
| 2614 | + if (node->proc) { | |
| 2615 | + target_node = node; | |
| 2616 | + binder_inc_node_nilocked(node, 1, 0, NULL); | |
| 2617 | + binder_inc_node_tmpref_ilocked(node); | |
| 2618 | + node->proc->tmp_ref++; | |
| 2619 | + *procp = node->proc; | |
| 2620 | + } else | |
| 2621 | + *error = BR_DEAD_REPLY; | |
| 2622 | + binder_node_inner_unlock(node); | |
| 2623 | + | |
| 2624 | + return target_node; | |
| 2625 | +} | |
| 2626 | + | |
| 2585 | 2627 | static void binder_transaction(struct binder_proc *proc, |
| 2586 | 2628 | struct binder_thread *thread, |
| 2587 | 2629 | struct binder_transaction_data *tr, int reply, |
| @@ -2685,43 +2727,35 @@ static void binder_transaction(struct binder_proc *proc, · 97 unmodified lines | ||
| 2685 | 2727 | ref = binder_get_ref_olocked(proc, tr->target.handle, |
| 2686 | 2728 | true); |
| 2687 | 2729 | if (ref) { |
| 2688 | − binder_inc_node(ref->node, 1, 0, NULL); | |
| 2689 | − target_node = ref->node; | |
| 2690 | − } | |
| 2691 | − binder_proc_unlock(proc); | |
| 2692 | − if (target_node == NULL) { | |
| 2730 | + target_node = binder_get_node_refs_for_txn( | |
| 2731 | + ref->node, &target_proc, | |
| 2732 | + &return_error); | |
| 2733 | + } else { | |
| 2693 | 2734 | binder_user_error("%d:%d got transaction to invalid handle\n", |
| 2694 | − proc->pid, thread->pid); | |
| 2735 | + proc->pid, thread->pid); | |
| 2695 | 2736 | return_error = BR_FAILED_REPLY; |
| 2696 | − return_error_param = -EINVAL; | |
| 2697 | − return_error_line = __LINE__; | |
| 2698 | − goto err_invalid_target_handle; | |
| 2699 | 2737 | } |
| 2738 | + binder_proc_unlock(proc); | |
| 2700 | 2739 | } else { |
| 2701 | 2740 | mutex_lock(&context->context_mgr_node_lock); |
| 2702 | 2741 | target_node = context->binder_context_mgr_node; |
| 2703 | − if (target_node == NULL) { | |
| 2742 | + if (target_node) | |
| 2743 | + target_node = binder_get_node_refs_for_txn( | |
| 2744 | + target_node, &target_proc, | |
| 2745 | + &return_error); | |
| 2746 | + else | |
| 2704 | 2747 | return_error = BR_DEAD_REPLY; |
| 2705 | − mutex_unlock(&context->context_mgr_node_lock); | |
| 2706 | − return_error_line = __LINE__; | |
| 2707 | − goto err_no_context_mgr_node; | |
| 2708 | − } | |
| 2709 | − binder_inc_node(target_node, 1, 0, NULL); | |
| 2710 | 2748 | mutex_unlock(&context->context_mgr_node_lock); |
| 2711 | 2749 | } |
| 2712 | − e->to_node = target_node->debug_id; | |
| 2713 | − binder_node_lock(target_node); | |
| 2714 | − target_proc = target_node->proc; | |
| 2715 | − if (target_proc == NULL) { | |
| 2716 | − binder_node_unlock(target_node); | |
| 2717 | − return_error = BR_DEAD_REPLY; | |
| 2750 | + if (!target_node) { | |
| 2751 | + /* | |
| 2752 | + * return_error is set above | |
| 2753 | + */ | |
| 2754 | + return_error_param = -EINVAL; | |
| 2718 | 2755 | return_error_line = __LINE__; |
| 2719 | 2756 | goto err_dead_binder; |
| 2720 | 2757 | } |
| 2721 | − binder_inner_proc_lock(target_proc); | |
| 2722 | − target_proc->tmp_ref++; | |
| 2723 | − binder_inner_proc_unlock(target_proc); | |
| 2724 | − binder_node_unlock(target_node); | |
| 2758 | + e->to_node = target_node->debug_id; | |
| 2725 | 2759 | if (security_binder_transaction(proc->tsk, |
| 2726 | 2760 | target_proc->tsk) < 0) { |
| 2727 | 2761 | return_error = BR_FAILED_REPLY; |
| @@ -3071,6 +3105,8 @@ static void binder_transaction(struct binder_proc *proc, · 343 unmodified lines | ||
| 3071 | 3105 | if (target_thread) |
| 3072 | 3106 | binder_thread_dec_tmpref(target_thread); |
| 3073 | 3107 | binder_proc_dec_tmpref(target_proc); |
| 3108 | + if (target_node) | |
| 3109 | + binder_dec_node_tmpref(target_node); | |
| 3074 | 3110 | /* |
| 3075 | 3111 | * write barrier to synchronize with initialization |
| 3076 | 3112 | * of log entry |
| @@ -3090,6 +3126,8 @@ err_bad_parent: · 13 unmodified lines | ||
| 3090 | 3126 | err_copy_data_failed: |
| 3091 | 3127 | trace_binder_transaction_failed_buffer_release(t->buffer); |
| 3092 | 3128 | binder_transaction_buffer_release(target_proc, t->buffer, offp); |
| 3129 | + if (target_node) | |
| 3130 | + binder_dec_node_tmpref(target_node); | |
| 3093 | 3131 | target_node = NULL; |
| 3094 | 3132 | t->buffer->transaction = NULL; |
| 3095 | 3133 | binder_alloc_free_buf(&target_proc->alloc, t->buffer); |
| @@ -3104,13 +3142,14 @@ err_bad_call_stack: · 8 unmodified lines | ||
| 3104 | 3142 | err_empty_call_stack: |
| 3105 | 3143 | err_dead_binder: |
| 3106 | 3144 | err_invalid_target_handle: |
| 3107 | −err_no_context_mgr_node: | |
| 3108 | 3145 | if (target_thread) |
| 3109 | 3146 | binder_thread_dec_tmpref(target_thread); |
| 3110 | 3147 | if (target_proc) |
| 3111 | 3148 | binder_proc_dec_tmpref(target_proc); |
| 3112 | − if (target_node) | |
| 3149 | + if (target_node) { | |
| 3113 | 3150 | binder_dec_node(target_node, 1, 0); |
| 3151 | + binder_dec_node_tmpref(target_node); | |
| 3152 | + } | |
| 3114 | 3153 | |
| 3115 | 3154 | binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, |
| 3116 | 3155 | "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n", |
| @@ -640,6 +640,7 @@ void vmbus_close(struct vmbus_channel *channel) · 639 unmodified lines | ||
| 640 | 640 | */ |
| 641 | 641 | return; |
| 642 | 642 | } |
| 643 | + mutex_lock(&vmbus_connection.channel_mutex); | |
| 643 | 644 | /* |
| 644 | 645 | * Close all the sub-channels first and then close the |
| 645 | 646 | * primary channel. |
| @@ -648,16 +649,15 @@ void vmbus_close(struct vmbus_channel *channel) · 2 unmodified lines | ||
| 648 | 649 | cur_channel = list_entry(cur, struct vmbus_channel, sc_list); |
| 649 | 650 | vmbus_close_internal(cur_channel); |
| 650 | 651 | if (cur_channel->rescind) { |
| 651 | − mutex_lock(&vmbus_connection.channel_mutex); | |
| 652 | − hv_process_channel_removal(cur_channel, | |
| 652 | + hv_process_channel_removal( | |
| 653 | 653 | cur_channel->offermsg.child_relid); |
| 654 | − mutex_unlock(&vmbus_connection.channel_mutex); | |
| 655 | 654 | } |
| 656 | 655 | } |
| 657 | 656 | /* |
| 658 | 657 | * Now close the primary. |
| 659 | 658 | */ |
| 660 | 659 | vmbus_close_internal(channel); |
| 660 | + mutex_unlock(&vmbus_connection.channel_mutex); | |
| 661 | 661 | } |
| 662 | 662 | EXPORT_SYMBOL_GPL(vmbus_close); |
| 663 | 663 | |
| @@ -159,7 +159,7 @@ static void vmbus_rescind_cleanup(struct vmbus_channel *channel) · 158 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | |
| 161 | 161 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
| 162 | − | |
| 162 | + channel->rescind = true; | |
| 163 | 163 | list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, |
| 164 | 164 | msglistentry) { |
| 165 | 165 | |
| @@ -381,14 +381,21 @@ static void vmbus_release_relid(u32 relid) · 215 unmodified lines | ||
| 381 | 381 | true); |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | −void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) | |
| 384 | +void hv_process_channel_removal(u32 relid) | |
| 385 | 385 | { |
| 386 | 386 | unsigned long flags; |
| 387 | − struct vmbus_channel *primary_channel; | |
| 387 | + struct vmbus_channel *primary_channel, *channel; | |
| 388 | 388 | |
| 389 | − BUG_ON(!channel->rescind); | |
| 390 | 389 | BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex)); |
| 391 | 390 | |
| 391 | + /* | |
| 392 | + * Make sure channel is valid as we may have raced. | |
| 393 | + */ | |
| 394 | + channel = relid2channel(relid); | |
| 395 | + if (!channel) | |
| 396 | + return; | |
| 397 | + | |
| 398 | + BUG_ON(!channel->rescind); | |
| 392 | 399 | if (channel->target_cpu != get_cpu()) { |
| 393 | 400 | put_cpu(); |
| 394 | 401 | smp_call_function_single(channel->target_cpu, |
| @@ -515,6 +522,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) · 120 unmodified lines | ||
| 515 | 522 | if (!fnew) { |
| 516 | 523 | if (channel->sc_creation_callback != NULL) |
| 517 | 524 | channel->sc_creation_callback(newchannel); |
| 525 | + newchannel->probe_done = true; | |
| 518 | 526 | return; |
| 519 | 527 | } |
| 520 | 528 | |
| @@ -834,7 +842,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) · 313 unmodified lines | ||
| 834 | 842 | { |
| 835 | 843 | struct vmbus_channel_rescind_offer *rescind; |
| 836 | 844 | struct vmbus_channel *channel; |
| 837 | − unsigned long flags; | |
| 838 | 845 | struct device *dev; |
| 839 | 846 | |
| 840 | 847 | rescind = (struct vmbus_channel_rescind_offer *)hdr; |
| @@ -873,16 +880,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) · 32 unmodified lines | ||
| 873 | 880 | return; |
| 874 | 881 | } |
| 875 | 882 | |
| 876 | − spin_lock_irqsave(&channel->lock, flags); | |
| 877 | − channel->rescind = true; | |
| 878 | − spin_unlock_irqrestore(&channel->lock, flags); | |
| 879 | − | |
| 880 | − /* | |
| 881 | − * Now that we have posted the rescind state, perform | |
| 882 | − * rescind related cleanup. | |
| 883 | − */ | |
| 884 | − vmbus_rescind_cleanup(channel); | |
| 885 | − | |
| 886 | 883 | /* |
| 887 | 884 | * Now wait for offer handling to complete. |
| 888 | 885 | */ |
| @@ -901,6 +898,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) · 12 unmodified lines | ||
| 901 | 898 | if (channel->device_obj) { |
| 902 | 899 | if (channel->chn_rescind_callback) { |
| 903 | 900 | channel->chn_rescind_callback(channel); |
| 901 | + vmbus_rescind_cleanup(channel); | |
| 904 | 902 | return; |
| 905 | 903 | } |
| 906 | 904 | /* |
| @@ -909,6 +907,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) · 2 unmodified lines | ||
| 909 | 907 | */ |
| 910 | 908 | dev = get_device(&channel->device_obj->device); |
| 911 | 909 | if (dev) { |
| 910 | + vmbus_rescind_cleanup(channel); | |
| 912 | 911 | vmbus_device_unregister(channel->device_obj); |
| 913 | 912 | put_device(dev); |
| 914 | 913 | } |
| @@ -921,16 +920,16 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) · 6 unmodified lines | ||
| 921 | 920 | * 1. Close all sub-channels first |
| 922 | 921 | * 2. Then close the primary channel. |
| 923 | 922 | */ |
| 923 | + mutex_lock(&vmbus_connection.channel_mutex); | |
| 924 | + vmbus_rescind_cleanup(channel); | |
| 924 | 925 | if (channel->state == CHANNEL_OPEN_STATE) { |
| 925 | 926 | /* |
| 926 | 927 | * The channel is currently not open; |
| 927 | 928 | * it is safe for us to cleanup the channel. |
| 928 | 929 | */ |
| 929 | − mutex_lock(&vmbus_connection.channel_mutex); | |
| 930 | − hv_process_channel_removal(channel, | |
| 931 | − channel->offermsg.child_relid); | |
| 932 | − mutex_unlock(&vmbus_connection.channel_mutex); | |
| 930 | + hv_process_channel_removal(rescind->child_relid); | |
| 933 | 931 | } |
| 932 | + mutex_unlock(&vmbus_connection.channel_mutex); | |
| 934 | 933 | } |
| 935 | 934 | } |
| 936 | 935 | |
| @@ -768,8 +768,7 @@ static void vmbus_device_release(struct device *device) · 767 unmodified lines | ||
| 768 | 768 | struct vmbus_channel *channel = hv_dev->channel; |
| 769 | 769 | |
| 770 | 770 | mutex_lock(&vmbus_connection.channel_mutex); |
| 771 | − hv_process_channel_removal(channel, | |
| 772 | − channel->offermsg.child_relid); | |
| 771 | + hv_process_channel_removal(channel->offermsg.child_relid); | |
| 773 | 772 | mutex_unlock(&vmbus_connection.channel_mutex); |
| 774 | 773 | kfree(hv_dev); |
| 775 | 774 | |
| @@ -127,6 +127,8 @@ · 126 unmodified lines | ||
| 127 | 127 | #define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */ |
| 128 | 128 | #define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */ |
| 129 | 129 | |
| 130 | +#define MEI_DEV_ID_GLK 0x319A /* Gemini Lake */ | |
| 131 | + | |
| 130 | 132 | #define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */ |
| 131 | 133 | #define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */ |
| 132 | 134 | |
| @@ -93,6 +93,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { · 92 unmodified lines | ||
| 93 | 93 | {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)}, |
| 94 | 94 | {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)}, |
| 95 | 95 | |
| 96 | + {MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)}, | |
| 97 | + | |
| 96 | 98 | {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)}, |
| 97 | 99 | {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)}, |
| 98 | 100 | |
| @@ -226,12 +228,15 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 127 unmodified lines | ||
| 226 | 228 | pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; |
| 227 | 229 | |
| 228 | 230 | /* |
| 229 | − * For not wake-able HW runtime pm framework | |
| 230 | − * can't be used on pci device level. | |
| 231 | − * Use domain runtime pm callbacks instead. | |
| 232 | − */ | |
| 233 | − if (!pci_dev_run_wake(pdev)) | |
| 234 | − mei_me_set_pm_domain(dev); | |
| 231 | + * ME maps runtime suspend/resume to D0i states, | |
| 232 | + * hence we need to go around native PCI runtime service which | |
| 233 | + * eventually brings the device into D3cold/hot state, | |
| 234 | + * but the mei device cannot wake up from D3 unlike from D0i3. | |
| 235 | + * To get around the PCI device native runtime pm, | |
| 236 | + * ME uses runtime pm domain handlers which take precedence | |
| 237 | + * over the driver's pm handlers. | |
| 238 | + */ | |
| 239 | + mei_me_set_pm_domain(dev); | |
| 235 | 240 | |
| 236 | 241 | if (mei_pg_is_enabled(dev)) |
| 237 | 242 | pm_runtime_put_noidle(&pdev->dev); |
| @@ -271,8 +276,7 @@ static void mei_me_shutdown(struct pci_dev *pdev) · 33 unmodified lines | ||
| 271 | 276 | dev_dbg(&pdev->dev, "shutdown\n"); |
| 272 | 277 | mei_stop(dev); |
| 273 | 278 | |
| 274 | − if (!pci_dev_run_wake(pdev)) | |
| 275 | − mei_me_unset_pm_domain(dev); | |
| 279 | + mei_me_unset_pm_domain(dev); | |
| 276 | 280 | |
| 277 | 281 | mei_disable_interrupts(dev); |
| 278 | 282 | free_irq(pdev->irq, dev); |
| @@ -300,8 +304,7 @@ static void mei_me_remove(struct pci_dev *pdev) · 21 unmodified lines | ||
| 300 | 304 | dev_dbg(&pdev->dev, "stop\n"); |
| 301 | 305 | mei_stop(dev); |
| 302 | 306 | |
| 303 | − if (!pci_dev_run_wake(pdev)) | |
| 304 | − mei_me_unset_pm_domain(dev); | |
| 307 | + mei_me_unset_pm_domain(dev); | |
| 305 | 308 | |
| 306 | 309 | mei_disable_interrupts(dev); |
| 307 | 310 | |
| @@ -144,12 +144,14 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 143 unmodified lines | ||
| 144 | 144 | pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; |
| 145 | 145 | |
| 146 | 146 | /* |
| 147 | − * For not wake-able HW runtime pm framework | |
| 148 | − * can't be used on pci device level. | |
| 149 | − * Use domain runtime pm callbacks instead. | |
| 150 | − */ | |
| 151 | − if (!pci_dev_run_wake(pdev)) | |
| 152 | − mei_txe_set_pm_domain(dev); | |
| 147 | + * TXE maps runtime suspend/resume to own power gating states, | |
| 148 | + * hence we need to go around native PCI runtime service which | |
| 149 | + * eventually brings the device into D3cold/hot state. | |
| 150 | + * But the TXE device cannot wake up from D3 unlike from own | |
| 151 | + * power gating. To get around PCI device native runtime pm, | |
| 152 | + * TXE uses runtime pm domain handlers which take precedence. | |
| 153 | + */ | |
| 154 | + mei_txe_set_pm_domain(dev); | |
| 153 | 155 | |
| 154 | 156 | pm_runtime_put_noidle(&pdev->dev); |
| 155 | 157 | |
| @@ -186,8 +188,7 @@ static void mei_txe_shutdown(struct pci_dev *pdev) · 30 unmodified lines | ||
| 186 | 188 | dev_dbg(&pdev->dev, "shutdown\n"); |
| 187 | 189 | mei_stop(dev); |
| 188 | 190 | |
| 189 | − if (!pci_dev_run_wake(pdev)) | |
| 190 | − mei_txe_unset_pm_domain(dev); | |
| 191 | + mei_txe_unset_pm_domain(dev); | |
| 191 | 192 | |
| 192 | 193 | mei_disable_interrupts(dev); |
| 193 | 194 | free_irq(pdev->irq, dev); |
| @@ -215,8 +216,7 @@ static void mei_txe_remove(struct pci_dev *pdev) · 21 unmodified lines | ||
| 215 | 216 | |
| 216 | 217 | mei_stop(dev); |
| 217 | 218 | |
| 218 | − if (!pci_dev_run_wake(pdev)) | |
| 219 | − mei_txe_unset_pm_domain(dev); | |
| 219 | + mei_txe_unset_pm_domain(dev); | |
| 220 | 220 | |
| 221 | 221 | mei_disable_interrupts(dev); |
| 222 | 222 | free_irq(pdev->irq, dev); |
| @@ -318,15 +318,7 @@ static int mei_txe_pm_runtime_suspend(struct device *device) · 95 unmodified lines | ||
| 318 | 318 | else |
| 319 | 319 | ret = -EAGAIN; |
| 320 | 320 | |
| 321 | − /* | |
| 322 | − * If everything is okay we're about to enter PCI low | |
| 323 | − * power state (D3) therefor we need to disable the | |
| 324 | − * interrupts towards host. | |
| 325 | − * However if device is not wakeable we do not enter | |
| 326 | − * D-low state and we need to keep the interrupt kicking | |
| 327 | − */ | |
| 328 | − if (!ret && pci_dev_run_wake(pdev)) | |
| 329 | − mei_disable_interrupts(dev); | |
| 321 | + /* keep irq on we are staying in D0 */ | |
| 330 | 322 | |
| 331 | 323 | dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); |
| 332 | 324 | |
| @@ -1403,7 +1403,7 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, · 1402 unmodified lines | ||
| 1403 | 1403 | const int *srv_version, int srv_vercnt, |
| 1404 | 1404 | int *nego_fw_version, int *nego_srv_version); |
| 1405 | 1405 | |
| 1406 | −void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); | |
| 1406 | +void hv_process_channel_removal(u32 relid); | |
| 1407 | 1407 | |
| 1408 | 1408 | void vmbus_setevent(struct vmbus_channel *channel); |
| 1409 | 1409 | /* |