Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ptdma-pci.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * AMD Passthru DMA device driver
 * -- Based on the CCP driver
 *
 * Copyright (C) 2016,2021 Advanced Micro Devices, Inc.
 *
 * Author: Sanjay R Mehta <sanju.mehta@amd.com>
 * Author: Tom Lendacky <thomas.lendacky@amd.com>
 * Author: Gary R Hook <gary.hook@amd.com>
 */


#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/pci_ids.h>
#include <linux/pci.h>
#include <linux/spinlock.h>

#include "ptdma.h"

struct pt_msix {
 int msix_count;
 struct msix_entry msix_entry;
};

/*
 * pt_alloc_struct - allocate and initialize the pt_device struct
 *
 * @dev: device struct of the PTDMA
 */

static struct pt_device *pt_alloc_struct(struct device *dev)
{
 struct pt_device *pt;

 pt = devm_kzalloc(dev, sizeof(*pt), GFP_KERNEL);

 if (!pt)
  return NULL;
 pt->dev = dev;

 INIT_LIST_HEAD(&pt->cmd);

 return pt;
}

static int pt_get_msix_irqs(struct pt_device *pt)
{
 struct pt_msix *pt_msix = pt->pt_msix;
 struct device *dev = pt->dev;
 struct pci_dev *pdev = to_pci_dev(dev);
 int ret;

 pt_msix->msix_entry.entry = 0;

 ret = pci_enable_msix_range(pdev, &pt_msix->msix_entry, 1, 1);
 if (ret < 0)
  return ret;

 pt_msix->msix_count = ret;

 pt->pt_irq = pt_msix->msix_entry.vector;

 return 0;
}

static int pt_get_msi_irq(struct pt_device *pt)
{
 struct device *dev = pt->dev;
 struct pci_dev *pdev = to_pci_dev(dev);
 int ret;

 ret = pci_enable_msi(pdev);
 if (ret)
  return ret;

 pt->pt_irq = pdev->irq;

 return 0;
}

static int pt_get_irqs(struct pt_device *pt)
{
 struct device *dev = pt->dev;
 int ret;

 ret = pt_get_msix_irqs(pt);
 if (!ret)
  return 0;

 /* Couldn't get MSI-X vectors, try MSI */
 dev_err(dev, "could not enable MSI-X (%d), trying MSI\n", ret);
 ret = pt_get_msi_irq(pt);
 if (!ret)
  return 0;

 /* Couldn't get MSI interrupt */
 dev_err(dev, "could not enable MSI (%d)\n", ret);

 return ret;
}

static void pt_free_irqs(struct pt_device *pt)
{
 struct pt_msix *pt_msix = pt->pt_msix;
 struct device *dev = pt->dev;
 struct pci_dev *pdev = to_pci_dev(dev);

 if (pt_msix->msix_count)
  pci_disable_msix(pdev);
 else if (pt->pt_irq)
  pci_disable_msi(pdev);

 pt->pt_irq = 0;
}

static int pt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
 struct pt_device *pt;
 struct pt_msix *pt_msix;
 struct device *dev = &pdev->dev;
 void __iomem * const *iomap_table;
 int bar_mask;
 int ret = -ENOMEM;

 pt = pt_alloc_struct(dev);
 if (!pt)
  goto e_err;

 pt_msix = devm_kzalloc(dev, sizeof(*pt_msix), GFP_KERNEL);
 if (!pt_msix)
  goto e_err;

 pt->pt_msix = pt_msix;
 pt->dev_vdata = (struct pt_dev_vdata *)id->driver_data;
 if (!pt->dev_vdata) {
  ret = -ENODEV;
  dev_err(dev, "missing driver data\n");
  goto e_err;
 }

 ret = pcim_enable_device(pdev);
 if (ret) {
  dev_err(dev, "pcim_enable_device failed (%d)\n", ret);
  goto e_err;
 }

 bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
 ret = pcim_iomap_regions(pdev, bar_mask, "ptdma");
 if (ret) {
  dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);
  goto e_err;
 }

 iomap_table = pcim_iomap_table(pdev);
 if (!iomap_table) {
  dev_err(dev, "pcim_iomap_table failed\n");
  ret = -ENOMEM;
  goto e_err;
 }

 pt->io_regs = iomap_table[pt->dev_vdata->bar];
 if (!pt->io_regs) {
  dev_err(dev, "ioremap failed\n");
  ret = -ENOMEM;
  goto e_err;
 }

 ret = pt_get_irqs(pt);
 if (ret)
  goto e_err;

 pci_set_master(pdev);

 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
 if (ret) {
  ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
  if (ret) {
   dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
    ret);
   goto e_err;
  }
 }

 dev_set_drvdata(dev, pt);

 if (pt->dev_vdata)
  ret = pt_core_init(pt);

 if (ret)
  goto e_err;

 return 0;

e_err:
 dev_err(dev, "initialization failed ret = %d\n", ret);

 return ret;
}

static void pt_pci_remove(struct pci_dev *pdev)
{
 struct device *dev = &pdev->dev;
 struct pt_device *pt = dev_get_drvdata(dev);

 if (!pt)
  return;

 if (pt->dev_vdata)
  pt_core_destroy(pt);

 pt_free_irqs(pt);
}

static const struct pt_dev_vdata dev_vdata[] = {
 {
  .bar = 2,
 },
};

static const struct pci_device_id pt_pci_table[] = {
 { PCI_VDEVICE(AMD, 0x1498), (kernel_ulong_t)&dev_vdata[0] },
 /* Last entry must be zero */
 { 0, }
};
MODULE_DEVICE_TABLE(pci, pt_pci_table);

static struct pci_driver pt_pci_driver = {
 .name = "ptdma",
 .id_table = pt_pci_table,
 .probe = pt_pci_probe,
 .remove = pt_pci_remove,
};

module_pci_driver(pt_pci_driver);

MODULE_AUTHOR("Sanjay R Mehta ");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AMD PassThru DMA driver");

Messung V0.5
C=95 H=89 G=91

¤ Dauer der Verarbeitung: 0.12 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge