Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/pci/endpoint/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 2 kB image not shown  

Quelle  pci-ep-msi.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * PCI Endpoint *Controller* (EPC) MSI library
 *
 * Copyright (C) 2025 NXP
 * Author: Frank Li <Frank.Li@nxp.com>
 */


#include <linux/device.h>
#include <linux/export.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/of_irq.h>
#include <linux/pci-epc.h>
#include <linux/pci-epf.h>
#include <linux/pci-ep-cfs.h>
#include <linux/pci-ep-msi.h>
#include <linux/slab.h>

static void pci_epf_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
{
 struct pci_epc *epc;
 struct pci_epf *epf;

 epc = pci_epc_get(dev_name(msi_desc_to_dev(desc)));
 if (IS_ERR(epc))
  return;

 epf = list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list);

 if (epf && epf->db_msg && desc->msi_index < epf->num_db)
  memcpy(&epf->db_msg[desc->msi_index].msg, msg, sizeof(*msg));

 pci_epc_put(epc);
}

int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db)
{
 struct pci_epc *epc = epf->epc;
 struct device *dev = &epf->dev;
 struct irq_domain *domain;
 void *msg;
 int ret;
 int i;

 /* TODO: Multi-EPF support */
 if (list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list) != epf) {
  dev_err(dev, "MSI doorbell doesn't support multiple EPF\n");
  return -EINVAL;
 }

 domain = of_msi_map_get_device_domain(epc->dev.parent, 0,
           DOMAIN_BUS_PLATFORM_MSI);
 if (!domain) {
  dev_err(dev, "Can't find MSI domain for EPC\n");
  return -ENODEV;
 }

 if (!irq_domain_is_msi_parent(domain))
  return -ENODEV;

 if (!irq_domain_is_msi_immutable(domain)) {
  dev_err(dev, "Mutable MSI controller not supported\n");
  return -ENODEV;
 }

 dev_set_msi_domain(epc->dev.parent, domain);

 msg = kcalloc(num_db, sizeof(struct pci_epf_doorbell_msg), GFP_KERNEL);
 if (!msg)
  return -ENOMEM;

 epf->num_db = num_db;
 epf->db_msg = msg;

 ret = platform_device_msi_init_and_alloc_irqs(epc->dev.parent, num_db,
            pci_epf_write_msi_msg);
 if (ret) {
  dev_err(dev, "Failed to allocate MSI\n");
  kfree(msg);
  return ret;
 }

 for (i = 0; i < num_db; i++)
  epf->db_msg[i].virq = msi_get_virq(epc->dev.parent, i);

 return ret;
}
EXPORT_SYMBOL_GPL(pci_epf_alloc_doorbell);

void pci_epf_free_doorbell(struct pci_epf *epf)
{
 platform_device_msi_free_irqs_all(epf->epc->dev.parent);

 kfree(epf->db_msg);
 epf->db_msg = NULL;
 epf->num_db = 0;
}
EXPORT_SYMBOL_GPL(pci_epf_free_doorbell);

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.