linux/drivers/cxl/pci.c

// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2020 Intel Corporation. All rights reserved. */
#include <asm-generic/unaligned.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/moduleparam.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/sizes.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/io.h>
#include "cxlmem.h"
#include "cxlpci.h"
#include "cxl.h"
#include "pmu.h"

/**
 * DOC: cxl pci
 *
 * This implements the PCI exclusive functionality for a CXL device as it is
 * defined by the Compute Express Link specification. CXL devices may surface
 * certain functionality even if it isn't CXL enabled. While this driver is
 * focused around the PCI specific aspects of a CXL device, it binds to the
 * specific CXL memory device class code, and therefore the implementation of
 * cxl_pci is focused around CXL memory devices.
 *
 * The driver has several responsibilities, mainly:
 *  - Create the memX device and register on the CXL bus.
 *  - Enumerate device's register interface and map them.
 *  - Registers nvdimm bridge device with cxl_core.
 *  - Registers a CXL mailbox with cxl_core.
 */

#define cxl_doorbell_busy(cxlds)

/* CXL 2.0 - 8.2.8.4 */
#define CXL_MAILBOX_TIMEOUT_MS

/*
 * CXL 2.0 ECN "Add Mailbox Ready Time" defines a capability field to
 * dictate how long to wait for the mailbox to become ready. The new
 * field allows the device to tell software the amount of time to wait
 * before mailbox ready. This field per the spec theoretically allows
 * for up to 255 seconds. 255 seconds is unreasonably long, its longer
 * than the maximum SATA port link recovery wait. Default to 60 seconds
 * until someone builds a CXL device that needs more time in practice.
 */
static unsigned short mbox_ready_timeout =;
module_param(mbox_ready_timeout, ushort, 0644);
MODULE_PARM_DESC();

static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds)
{}

#define cxl_err(dev, status, msg)

#define cxl_cmd_err(dev, cmd, status, msg)

/*
 * Threaded irq dev_id's must be globally unique.  cxl_dev_id provides a unique
 * wrapper object for each irq within the same cxlds.
 */
struct cxl_dev_id {};

static int cxl_request_irq(struct cxl_dev_state *cxlds, int irq,
			   irq_handler_t thread_fn)
{}

static bool cxl_mbox_background_complete(struct cxl_dev_state *cxlds)
{}

static irqreturn_t cxl_pci_mbox_irq(int irq, void *id)
{}

/*
 * Sanitization operation polling mode.
 */
static void cxl_mbox_sanitize_work(struct work_struct *work)
{}

/**
 * __cxl_pci_mbox_send_cmd() - Execute a mailbox command
 * @mds: The memory device driver data
 * @mbox_cmd: Command to send to the memory device.
 *
 * Context: Any context. Expects mbox_mutex to be held.
 * Return: -ETIMEDOUT if timeout occurred waiting for completion. 0 on success.
 *         Caller should check the return code in @mbox_cmd to make sure it
 *         succeeded.
 *
 * This is a generic form of the CXL mailbox send command thus only using the
 * registers defined by the mailbox capability ID - CXL 2.0 8.2.8.4. Memory
 * devices, and perhaps other types of CXL devices may have further information
 * available upon error conditions. Driver facilities wishing to send mailbox
 * commands should use the wrapper command.
 *
 * The CXL spec allows for up to two mailboxes. The intention is for the primary
 * mailbox to be OS controlled and the secondary mailbox to be used by system
 * firmware. This allows the OS and firmware to communicate with the device and
 * not need to coordinate with each other. The driver only uses the primary
 * mailbox.
 */
static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds,
				   struct cxl_mbox_cmd *mbox_cmd)
{}

static int cxl_pci_mbox_send(struct cxl_memdev_state *mds,
			     struct cxl_mbox_cmd *cmd)
{}

static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds, bool irq_avail)
{}

/*
 * Assume that any RCIEP that emits the CXL memory expander class code
 * is an RCD
 */
static bool is_cxl_restricted(struct pci_dev *pdev)
{}

static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
				  struct cxl_register_map *map)
{}

static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
			      struct cxl_register_map *map)
{}

static int cxl_pci_ras_unmask(struct pci_dev *pdev)
{}

static void free_event_buf(void *buf)
{}

/*
 * There is a single buffer for reading event logs from the mailbox.  All logs
 * share this buffer protected by the mds->event_log_lock.
 */
static int cxl_mem_alloc_event_buf(struct cxl_memdev_state *mds)
{}

static bool cxl_alloc_irq_vectors(struct pci_dev *pdev)
{}

static irqreturn_t cxl_event_thread(int irq, void *id)
{}

static int cxl_event_req_irq(struct cxl_dev_state *cxlds, u8 setting)
{}

static int cxl_event_get_int_policy(struct cxl_memdev_state *mds,
				    struct cxl_event_interrupt_policy *policy)
{}

static int cxl_event_config_msgnums(struct cxl_memdev_state *mds,
				    struct cxl_event_interrupt_policy *policy)
{}

static int cxl_event_irqsetup(struct cxl_memdev_state *mds)
{}

static bool cxl_event_int_is_fw(u8 setting)
{}

static int cxl_event_config(struct pci_host_bridge *host_bridge,
			    struct cxl_memdev_state *mds, bool irq_avail)
{}

static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{}

static const struct pci_device_id cxl_mem_pci_tbl[] =;
MODULE_DEVICE_TABLE(pci, cxl_mem_pci_tbl);

static pci_ers_result_t cxl_slot_reset(struct pci_dev *pdev)
{}

static void cxl_error_resume(struct pci_dev *pdev)
{}

static void cxl_reset_done(struct pci_dev *pdev)
{}

static const struct pci_error_handlers cxl_error_handlers =;

static struct pci_driver cxl_pci_driver =;

#define CXL_EVENT_HDR_FLAGS_REC_SEVERITY
static void cxl_handle_cper_event(enum cxl_event_type ev_type,
				  struct cxl_cper_event_rec *rec)
{}

static void cxl_cper_work_fn(struct work_struct *work)
{}
static DECLARE_WORK(cxl_cper_work, cxl_cper_work_fn);

static int __init cxl_pci_driver_init(void)
{}

static void __exit cxl_pci_driver_exit(void)
{}

module_init();
module_exit(cxl_pci_driver_exit);
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_IMPORT_NS();