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 unsigned long pci_handle_size
= 0;
20 efi_handle_t
*pci_handle
= NULL
;
26 status
= efi_bs_call(locate_handle
, EFI_LOCATE_BY_PROTOCOL
, &pci_proto
,
27 NULL
, &pci_handle_size
, NULL
);
29 if (status
!= EFI_BUFFER_TOO_SMALL
) {
30 if (status
!= EFI_SUCCESS
&& status
!= EFI_NOT_FOUND
)
31 efi_err("Failed to locate PCI I/O handles'\n");
35 status
= efi_bs_call(allocate_pool
, EFI_LOADER_DATA
, pci_handle_size
,
36 (void **)&pci_handle
);
37 if (status
!= EFI_SUCCESS
) {
38 efi_err("Failed to allocate memory for 'pci_handle'\n");
42 status
= efi_bs_call(locate_handle
, EFI_LOCATE_BY_PROTOCOL
, &pci_proto
,
43 NULL
, &pci_handle_size
, pci_handle
);
44 if (status
!= EFI_SUCCESS
) {
45 efi_err("Failed to locate PCI I/O handles'\n");
49 for_each_efi_handle(handle
, pci_handle
, pci_handle_size
, i
) {
50 efi_pci_io_protocol_t
*pci
;
51 unsigned long segment_nr
, bus_nr
, device_nr
, func_nr
;
53 status
= efi_bs_call(handle_protocol
, handle
, &pci_proto
,
55 if (status
!= EFI_SUCCESS
)
59 * Disregard devices living on bus 0 - these are not behind a
60 * bridge so no point in disconnecting them from their drivers.
62 status
= efi_call_proto(pci
, get_location
, &segment_nr
, &bus_nr
,
63 &device_nr
, &func_nr
);
64 if (status
!= EFI_SUCCESS
|| bus_nr
== 0)
68 * Don't disconnect VGA controllers so we don't risk losing
69 * access to the framebuffer. Drivers for true PCIe graphics
70 * controllers that are behind a PCIe root port do not use
71 * DMA to implement the GOP framebuffer anyway [although they
72 * may use it in their implementation of Gop->Blt()], and so
73 * disabling DMA in the PCI bridge should not interfere with
74 * normal operation of the device.
76 status
= efi_call_proto(pci
, pci
.read
, EfiPciIoWidthUint16
,
77 PCI_CLASS_DEVICE
, 1, &class);
78 if (status
!= EFI_SUCCESS
|| class == PCI_CLASS_DISPLAY_VGA
)
81 /* Disconnect this handle from all its drivers */
82 efi_bs_call(disconnect_controller
, handle
, NULL
, NULL
);
85 for_each_efi_handle(handle
, pci_handle
, pci_handle_size
, i
) {
86 efi_pci_io_protocol_t
*pci
;
88 status
= efi_bs_call(handle_protocol
, handle
, &pci_proto
,
90 if (status
!= EFI_SUCCESS
|| !pci
)
93 status
= efi_call_proto(pci
, pci
.read
, EfiPciIoWidthUint16
,
94 PCI_CLASS_DEVICE
, 1, &class);
96 if (status
!= EFI_SUCCESS
|| class != PCI_CLASS_BRIDGE_PCI
)
99 /* Disable busmastering */
100 status
= efi_call_proto(pci
, pci
.read
, EfiPciIoWidthUint16
,
101 PCI_COMMAND
, 1, &command
);
102 if (status
!= EFI_SUCCESS
|| !(command
& PCI_COMMAND_MASTER
))
105 command
&= ~PCI_COMMAND_MASTER
;
106 status
= efi_call_proto(pci
, pci
.write
, EfiPciIoWidthUint16
,
107 PCI_COMMAND
, 1, &command
);
108 if (status
!= EFI_SUCCESS
)
109 efi_err("Failed to disable PCI busmastering\n");
113 efi_bs_call(free_pool
, pci_handle
);