1 // SPDX-License-Identifier: GPL-2.0
3 * PCI-related functions used by the EFI stub on multiple
6 * Copyright 2019 Google, LLC
10 #include <linux/pci.h>
16 void efi_pci_disable_bridge_busmaster(void)
18 efi_guid_t pci_proto
= EFI_PCI_IO_PROTOCOL_GUID
;
19 efi_handle_t
*pci_handle
__free(efi_pool
) = NULL
;
20 unsigned long pci_handle_num
;
25 status
= efi_bs_call(locate_handle_buffer
, EFI_LOCATE_BY_PROTOCOL
,
26 &pci_proto
, NULL
, &pci_handle_num
, &pci_handle
);
27 if (status
!= EFI_SUCCESS
) {
28 efi_err("Failed to locate PCI I/O handles\n");
32 for_each_efi_handle(handle
, pci_handle
, pci_handle_num
) {
33 efi_pci_io_protocol_t
*pci
;
34 unsigned long segment_nr
, bus_nr
, device_nr
, func_nr
;
36 status
= efi_bs_call(handle_protocol
, handle
, &pci_proto
,
38 if (status
!= EFI_SUCCESS
)
42 * Disregard devices living on bus 0 - these are not behind a
43 * bridge so no point in disconnecting them from their drivers.
45 status
= efi_call_proto(pci
, get_location
, &segment_nr
, &bus_nr
,
46 &device_nr
, &func_nr
);
47 if (status
!= EFI_SUCCESS
|| bus_nr
== 0)
51 * Don't disconnect VGA controllers so we don't risk losing
52 * access to the framebuffer. Drivers for true PCIe graphics
53 * controllers that are behind a PCIe root port do not use
54 * DMA to implement the GOP framebuffer anyway [although they
55 * may use it in their implementation of Gop->Blt()], and so
56 * disabling DMA in the PCI bridge should not interfere with
57 * normal operation of the device.
59 status
= efi_call_proto(pci
, pci
.read
, EfiPciIoWidthUint16
,
60 PCI_CLASS_DEVICE
, 1, &class);
61 if (status
!= EFI_SUCCESS
|| class == PCI_CLASS_DISPLAY_VGA
)
64 /* Disconnect this handle from all its drivers */
65 efi_bs_call(disconnect_controller
, handle
, NULL
, NULL
);
68 for_each_efi_handle(handle
, pci_handle
, pci_handle_num
) {
69 efi_pci_io_protocol_t
*pci
;
71 status
= efi_bs_call(handle_protocol
, handle
, &pci_proto
,
73 if (status
!= EFI_SUCCESS
|| !pci
)
76 status
= efi_call_proto(pci
, pci
.read
, EfiPciIoWidthUint16
,
77 PCI_CLASS_DEVICE
, 1, &class);
79 if (status
!= EFI_SUCCESS
|| class != PCI_CLASS_BRIDGE_PCI
)
82 /* Disable busmastering */
83 status
= efi_call_proto(pci
, pci
.read
, EfiPciIoWidthUint16
,
84 PCI_COMMAND
, 1, &command
);
85 if (status
!= EFI_SUCCESS
|| !(command
& PCI_COMMAND_MASTER
))
88 command
&= ~PCI_COMMAND_MASTER
;
89 status
= efi_call_proto(pci
, pci
.write
, EfiPciIoWidthUint16
,
90 PCI_COMMAND
, 1, &command
);
91 if (status
!= EFI_SUCCESS
)
92 efi_err("Failed to disable PCI busmastering\n");