// SPDX-License-Identifier: GPL-2.0 /* * Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ /** * DOC: Nitro Enclaves (NE) PCI device driver. */ #include <linux/delay.h> #include <linux/device.h> #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/nitro_enclaves.h> #include <linux/pci.h> #include <linux/types.h> #include <linux/wait.h> #include "ne_misc_dev.h" #include "ne_pci_dev.h" /** * NE_DEFAULT_TIMEOUT_MSECS - Default timeout to wait for a reply from * the NE PCI device. */ #define NE_DEFAULT_TIMEOUT_MSECS … static const struct pci_device_id ne_pci_ids[] = …; MODULE_DEVICE_TABLE(pci, ne_pci_ids); /** * ne_submit_request() - Submit command request to the PCI device based on the * command type. * @pdev: PCI device to send the command to. * @cmd_type: Command type of the request sent to the PCI device. * @cmd_request: Command request payload. * @cmd_request_size: Size of the command request payload. * * Context: Process context. This function is called with the ne_pci_dev mutex held. */ static void ne_submit_request(struct pci_dev *pdev, enum ne_pci_dev_cmd_type cmd_type, void *cmd_request, size_t cmd_request_size) { … } /** * ne_retrieve_reply() - Retrieve reply from the PCI device. * @pdev: PCI device to receive the reply from. * @cmd_reply: Command reply payload. * @cmd_reply_size: Size of the command reply payload. * * Context: Process context. This function is called with the ne_pci_dev mutex held. */ static void ne_retrieve_reply(struct pci_dev *pdev, struct ne_pci_dev_cmd_reply *cmd_reply, size_t cmd_reply_size) { … } /** * ne_wait_for_reply() - Wait for a reply of a PCI device command. * @pdev: PCI device for which a reply is waited. * * Context: Process context. This function is called with the ne_pci_dev mutex held. * Return: * * 0 on success. * * Negative return value on failure. */ static int ne_wait_for_reply(struct pci_dev *pdev) { … } int ne_do_request(struct pci_dev *pdev, enum ne_pci_dev_cmd_type cmd_type, void *cmd_request, size_t cmd_request_size, struct ne_pci_dev_cmd_reply *cmd_reply, size_t cmd_reply_size) { … } /** * ne_reply_handler() - Interrupt handler for retrieving a reply matching a * request sent to the PCI device for enclave lifetime * management. * @irq: Received interrupt for a reply sent by the PCI device. * @args: PCI device private data structure. * * Context: Interrupt context. * Return: * * IRQ_HANDLED on handled interrupt. */ static irqreturn_t ne_reply_handler(int irq, void *args) { … } /** * ne_event_work_handler() - Work queue handler for notifying enclaves on a * state change received by the event interrupt * handler. * @work: Item containing the NE PCI device for which an out-of-band event * was issued. * * An out-of-band event is being issued by the Nitro Hypervisor when at least * one enclave is changing state without client interaction. * * Context: Work queue context. */ static void ne_event_work_handler(struct work_struct *work) { … } /** * ne_event_handler() - Interrupt handler for PCI device out-of-band events. * This interrupt does not supply any data in the MMIO * region. It notifies a change in the state of any of * the launched enclaves. * @irq: Received interrupt for an out-of-band event. * @args: PCI device private data structure. * * Context: Interrupt context. * Return: * * IRQ_HANDLED on handled interrupt. */ static irqreturn_t ne_event_handler(int irq, void *args) { … } /** * ne_setup_msix() - Setup MSI-X vectors for the PCI device. * @pdev: PCI device to setup the MSI-X for. * * Context: Process context. * Return: * * 0 on success. * * Negative return value on failure. */ static int ne_setup_msix(struct pci_dev *pdev) { … } /** * ne_teardown_msix() - Teardown MSI-X vectors for the PCI device. * @pdev: PCI device to teardown the MSI-X for. * * Context: Process context. */ static void ne_teardown_msix(struct pci_dev *pdev) { … } /** * ne_pci_dev_enable() - Select the PCI device version and enable it. * @pdev: PCI device to select version for and then enable. * * Context: Process context. * Return: * * 0 on success. * * Negative return value on failure. */ static int ne_pci_dev_enable(struct pci_dev *pdev) { … } /** * ne_pci_dev_disable() - Disable the PCI device. * @pdev: PCI device to disable. * * Context: Process context. */ static void ne_pci_dev_disable(struct pci_dev *pdev) { … } /** * ne_pci_probe() - Probe function for the NE PCI device. * @pdev: PCI device to match with the NE PCI driver. * @id : PCI device id table associated with the NE PCI driver. * * Context: Process context. * Return: * * 0 on success. * * Negative return value on failure. */ static int ne_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { … } /** * ne_pci_remove() - Remove function for the NE PCI device. * @pdev: PCI device associated with the NE PCI driver. * * Context: Process context. */ static void ne_pci_remove(struct pci_dev *pdev) { … } /** * ne_pci_shutdown() - Shutdown function for the NE PCI device. * @pdev: PCI device associated with the NE PCI driver. * * Context: Process context. */ static void ne_pci_shutdown(struct pci_dev *pdev) { … } /* * TODO: Add suspend / resume functions for power management w/ CONFIG_PM, if * needed. */ /* NE PCI device driver. */ struct pci_driver ne_pci_driver = …;