pci.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * PCI-related functions used by the EFI stub on multiple
  4. * architectures.
  5. *
  6. * Copyright 2019 Google, LLC
  7. */
  8. #include <linux/efi.h>
  9. #include <linux/pci.h>
  10. #include <asm/efi.h>
  11. #include "efistub.h"
  12. void efi_pci_disable_bridge_busmaster(void)
  13. {
  14. efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
  15. unsigned long pci_handle_size = 0;
  16. efi_handle_t *pci_handle = NULL;
  17. efi_handle_t handle;
  18. efi_status_t status;
  19. u16 class, command;
  20. int i;
  21. status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
  22. NULL, &pci_handle_size, NULL);
  23. if (status != EFI_BUFFER_TOO_SMALL) {
  24. if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
  25. efi_err("Failed to locate PCI I/O handles'\n");
  26. return;
  27. }
  28. status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, pci_handle_size,
  29. (void **)&pci_handle);
  30. if (status != EFI_SUCCESS) {
  31. efi_err("Failed to allocate memory for 'pci_handle'\n");
  32. return;
  33. }
  34. status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
  35. NULL, &pci_handle_size, pci_handle);
  36. if (status != EFI_SUCCESS) {
  37. efi_err("Failed to locate PCI I/O handles'\n");
  38. goto free_handle;
  39. }
  40. for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
  41. efi_pci_io_protocol_t *pci;
  42. unsigned long segment_nr, bus_nr, device_nr, func_nr;
  43. status = efi_bs_call(handle_protocol, handle, &pci_proto,
  44. (void **)&pci);
  45. if (status != EFI_SUCCESS)
  46. continue;
  47. /*
  48. * Disregard devices living on bus 0 - these are not behind a
  49. * bridge so no point in disconnecting them from their drivers.
  50. */
  51. status = efi_call_proto(pci, get_location, &segment_nr, &bus_nr,
  52. &device_nr, &func_nr);
  53. if (status != EFI_SUCCESS || bus_nr == 0)
  54. continue;
  55. /*
  56. * Don't disconnect VGA controllers so we don't risk losing
  57. * access to the framebuffer. Drivers for true PCIe graphics
  58. * controllers that are behind a PCIe root port do not use
  59. * DMA to implement the GOP framebuffer anyway [although they
  60. * may use it in their implementation of Gop->Blt()], and so
  61. * disabling DMA in the PCI bridge should not interfere with
  62. * normal operation of the device.
  63. */
  64. status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
  65. PCI_CLASS_DEVICE, 1, &class);
  66. if (status != EFI_SUCCESS || class == PCI_CLASS_DISPLAY_VGA)
  67. continue;
  68. /* Disconnect this handle from all its drivers */
  69. efi_bs_call(disconnect_controller, handle, NULL, NULL);
  70. }
  71. for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
  72. efi_pci_io_protocol_t *pci;
  73. status = efi_bs_call(handle_protocol, handle, &pci_proto,
  74. (void **)&pci);
  75. if (status != EFI_SUCCESS || !pci)
  76. continue;
  77. status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
  78. PCI_CLASS_DEVICE, 1, &class);
  79. if (status != EFI_SUCCESS || class != PCI_CLASS_BRIDGE_PCI)
  80. continue;
  81. /* Disable busmastering */
  82. status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
  83. PCI_COMMAND, 1, &command);
  84. if (status != EFI_SUCCESS || !(command & PCI_COMMAND_MASTER))
  85. continue;
  86. command &= ~PCI_COMMAND_MASTER;
  87. status = efi_call_proto(pci, pci.write, EfiPciIoWidthUint16,
  88. PCI_COMMAND, 1, &command);
  89. if (status != EFI_SUCCESS)
  90. efi_err("Failed to disable PCI busmastering\n");
  91. }
  92. free_handle:
  93. efi_bs_call(free_pool, pci_handle);
  94. }